diff --git a/.mailmap b/.mailmap index c109074021d1..122751a6be8a 100644 --- a/.mailmap +++ b/.mailmap @@ -74,6 +74,7 @@ Benoît Cortier Bheesham Persaud Bheesham Persaud Björn Steinbrink blake2-ppc +blyxyas Alejandra González boolean_coercion Boris Egorov bors bors[bot] <26634292+bors[bot]@users.noreply.github.com> diff --git a/Cargo.lock b/Cargo.lock index c9d5f1744f3b..01e4fef5e147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -697,6 +697,7 @@ dependencies = [ "getopts", "glob", "home", + "indexmap 2.0.0", "lazycell", "libc", "miow", @@ -3418,6 +3419,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_type_ir", "smallvec", "thin-vec", "tracing", @@ -3838,7 +3840,7 @@ dependencies = [ [[package]] name = "rustc_fluent_macro" -version = "0.1.0" +version = "0.0.0" dependencies = [ "annotate-snippets", "fluent-bundle", @@ -3914,7 +3916,7 @@ dependencies = [ [[package]] name = "rustc_hir_typeck" -version = "0.1.0" +version = "0.0.0" dependencies = [ "rustc_ast", "rustc_attr", @@ -4042,7 +4044,7 @@ dependencies = [ [[package]] name = "rustc_lexer" -version = "0.1.0" +version = "0.0.0" dependencies = [ "expect-test", "unicode-properties", @@ -4111,7 +4113,7 @@ dependencies = [ [[package]] name = "rustc_macros" -version = "0.1.0" +version = "0.0.0" dependencies = [ "proc-macro2", "quote", @@ -4595,7 +4597,7 @@ dependencies = [ [[package]] name = "rustc_transmute" -version = "0.1.0" +version = "0.0.0" dependencies = [ "itertools", "rustc_data_structures", diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index f0632ac92e96..e0948471acb5 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -14,6 +14,8 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +# depends on Mutability and Movability, which could be uplifted into a common crate. +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e8cbd7b69fbe..e94e26a63bc6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -34,6 +34,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +pub use rustc_type_ir::{Movability, Mutability}; use std::fmt; use std::mem; use thin_vec::{thin_vec, ThinVec}; @@ -800,57 +801,6 @@ pub enum PatKind { MacCall(P), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] -pub enum Mutability { - // N.B. Order is deliberate, so that Not < Mut - Not, - Mut, -} - -impl Mutability { - pub fn invert(self) -> Self { - match self { - Mutability::Mut => Mutability::Not, - Mutability::Not => Mutability::Mut, - } - } - - /// Returns `""` (empty string) or `"mut "` depending on the mutability. - pub fn prefix_str(self) -> &'static str { - match self { - Mutability::Mut => "mut ", - Mutability::Not => "", - } - } - - /// Returns `"&"` or `"&mut "` depending on the mutability. - pub fn ref_prefix_str(self) -> &'static str { - match self { - Mutability::Not => "&", - Mutability::Mut => "&mut ", - } - } - - /// Returns `""` (empty string) or `"mutably "` depending on the mutability. - pub fn mutably_str(self) -> &'static str { - match self { - Mutability::Not => "", - Mutability::Mut => "mutably ", - } - } - - /// Return `true` if self is mutable - pub fn is_mut(self) -> bool { - matches!(self, Self::Mut) - } - - /// Return `true` if self is **not** mutable - pub fn is_not(self) -> bool { - matches!(self, Self::Not) - } -} - /// The kind of borrow in an `AddrOf` expression, /// e.g., `&place` or `&raw const place`. #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -1579,17 +1529,6 @@ pub enum CaptureBy { Ref, } -/// The movability of a generator / closure literal: -/// whether a generator contains self-references, causing it to be `!Unpin`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] -#[derive(HashStable_Generic)] -pub enum Movability { - /// May contain self-references, `!Unpin`. - Static, - /// Must not contain self-references, `Unpin`. - Movable, -} - /// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum ClosureBinder { diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index ddc7c8ee8258..ada5c95dc34d 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -60,7 +60,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_span::HashStableContext { +pub trait HashStableContext: + rustc_type_ir::HashStableContext + rustc_span::HashStableContext +{ fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index ee5543703052..fb0e5811c267 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -328,26 +328,19 @@ fn check_opaque_type_well_formed<'tcx>( // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - let mut obligations = vec![]; - infcx - .insert_hidden_type( - OpaqueTypeKey { def_id, args: identity_args }, - &ObligationCause::misc(definition_span, def_id), - param_env, - definition_ty, - true, - &mut obligations, - ) - .unwrap(); - infcx.add_item_bounds_for_hidden_type( - def_id.to_def_id(), - identity_args, - ObligationCause::misc(definition_span, def_id), - param_env, - definition_ty, - &mut obligations, - ); - ocx.register_obligations(obligations); + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); + ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) + .map_err(|err| { + infcx + .err_ctxt() + .report_mismatched_types( + &ObligationCause::misc(definition_span, def_id), + opaque_ty, + definition_ty, + err, + ) + .emit() + })?; // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 763186a58bf9..7ad2d03a5edd 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, ExpressionId, Operand}; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -43,11 +43,11 @@ impl Counter { Self { kind: CounterKind::Expression, id: expression_id.as_u32() } } - pub(crate) fn from_operand(operand: Operand) -> Self { - match operand { - Operand::Zero => Self::ZERO, - Operand::Counter(id) => Self::counter_value_reference(id), - Operand::Expression(id) => Self::expression(id), + pub(crate) fn from_term(term: CovTerm) -> Self { + match term { + CovTerm::Zero => Self::ZERO, + CovTerm::Counter(id) => Self::counter_value_reference(id), + CovTerm::Expression(id) => Self::expression(id), } } } @@ -73,17 +73,6 @@ pub struct CounterExpression { pub rhs: Counter, } -impl CounterExpression { - /// The dummy expression `(0 - 0)` has a representation of all zeroes, - /// making it marginally more efficient to initialize than `(0 + 0)`. - pub(crate) const DUMMY: Self = - Self { lhs: Counter::ZERO, kind: ExprKind::Subtract, rhs: Counter::ZERO }; - - pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self { - Self { kind, lhs, rhs } - } -} - /// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. /// /// Must match the layout of `LLVMRustCounterMappingRegionKind`. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 55f43aa53417..84319b4ba2d3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,64 +1,78 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::FxIndexSet; -use rustc_index::IndexVec; -use rustc_middle::mir::coverage::{CodeRegion, CounterId, ExpressionId, Op, Operand}; +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::coverage::{ + CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op, +}; use rustc_middle::ty::Instance; -use rustc_middle::ty::TyCtxt; -#[derive(Clone, Debug, PartialEq)] -pub struct Expression { - lhs: Operand, - op: Op, - rhs: Operand, - code_regions: Vec, -} - -/// Collects all of the coverage regions associated with (a) injected counters, (b) counter -/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero), -/// for a given Function. This struct also stores the `function_source_hash`, -/// computed during instrumentation, and forwarded with counters. -/// -/// Note, it may be important to understand LLVM's definitions of `unreachable` regions versus "gap -/// regions" (or "gap areas"). A gap region is a code region within a counted region (either counter -/// or expression), but the line or lines in the gap region are not executable (such as lines with -/// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count -/// for a gap area is only used as the line execution count if there are no other regions on a -/// line." +/// Holds all of the coverage mapping data associated with a function instance, +/// collected during traversal of `Coverage` statements in the function's MIR. #[derive(Debug)] pub struct FunctionCoverage<'tcx> { - instance: Instance<'tcx>, - source_hash: u64, + /// Coverage info that was attached to this function by the instrumentor. + function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, - counters: IndexVec>>, - expressions: IndexVec>, - unreachable_regions: Vec, + + /// Tracks which counters have been seen, so that we can identify mappings + /// to counters that were optimized out, and set them to zero. + counters_seen: BitSet, + /// Contains all expression IDs that have been seen in an `ExpressionUsed` + /// coverage statement, plus all expression IDs that aren't directly used + /// by any mappings (and therefore do not have expression-used statements). + /// After MIR traversal is finished, we can conclude that any IDs missing + /// from this set must have had their statements deleted by MIR opts. + expressions_seen: BitSet, } impl<'tcx> FunctionCoverage<'tcx> { /// Creates a new set of coverage data for a used (called) function. - pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - Self::create(tcx, instance, true) + pub fn new( + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + ) -> Self { + Self::create(instance, function_coverage_info, true) } /// Creates a new set of coverage data for an unused (never called) function. - pub fn unused(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - Self::create(tcx, instance, false) + pub fn unused( + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + ) -> Self { + Self::create(instance, function_coverage_info, false) } - fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { - let coverageinfo = tcx.coverageinfo(instance.def); + fn create( + instance: Instance<'tcx>, + function_coverage_info: &'tcx FunctionCoverageInfo, + is_used: bool, + ) -> Self { + let num_counters = function_coverage_info.num_counters; + let num_expressions = function_coverage_info.expressions.len(); debug!( - "FunctionCoverage::create(instance={:?}) has coverageinfo={:?}. is_used={}", - instance, coverageinfo, is_used + "FunctionCoverage::create(instance={instance:?}) has \ + num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}" ); + + // Create a filled set of expression IDs, so that expressions not + // directly used by mappings will be treated as "seen". + // (If they end up being unused, LLVM will delete them for us.) + let mut expressions_seen = BitSet::new_filled(num_expressions); + // For each expression ID that is directly used by one or more mappings, + // mark it as not-yet-seen. This indicates that we expect to see a + // corresponding `ExpressionUsed` statement during MIR traversal. + for Mapping { term, .. } in &function_coverage_info.mappings { + if let &CovTerm::Expression(id) = term { + expressions_seen.remove(id); + } + } + Self { - instance, - source_hash: 0, // will be set with the first `add_counter()` + function_coverage_info, is_used, - counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), - expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), - unreachable_regions: Vec::new(), + counters_seen: BitSet::new_empty(num_counters), + expressions_seen, } } @@ -67,135 +81,94 @@ impl<'tcx> FunctionCoverage<'tcx> { self.is_used } - /// Sets the function source hash value. If called multiple times for the same function, all - /// calls should have the same hash value. - pub fn set_function_source_hash(&mut self, source_hash: u64) { - if self.source_hash == 0 { - self.source_hash = source_hash; - } else { - debug_assert_eq!(source_hash, self.source_hash); - } - } - - /// Adds code regions to be counted by an injected counter intrinsic. + /// Marks a counter ID as having been seen in a counter-increment statement. #[instrument(level = "debug", skip(self))] - pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) { - if code_regions.is_empty() { - return; - } - - let slot = &mut self.counters[id]; - match slot { - None => *slot = Some(code_regions.to_owned()), - // If this counter ID slot has already been filled, it should - // contain identical information. - Some(ref previous_regions) => assert_eq!( - previous_regions, code_regions, - "add_counter: code regions for id changed" - ), - } + pub(crate) fn mark_counter_id_seen(&mut self, id: CounterId) { + self.counters_seen.insert(id); } - /// Adds information about a coverage expression, along with zero or more - /// code regions mapped to that expression. - /// - /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other - /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity - /// between operands that are counter IDs and operands that are expression IDs. + /// Marks an expression ID as having been seen in an expression-used statement. #[instrument(level = "debug", skip(self))] - pub(crate) fn add_counter_expression( - &mut self, - expression_id: ExpressionId, - lhs: Operand, - op: Op, - rhs: Operand, - code_regions: &[CodeRegion], - ) { - debug_assert!( - expression_id.as_usize() < self.expressions.len(), - "expression_id {} is out of range for expressions.len() = {} - for {:?}", - expression_id.as_usize(), - self.expressions.len(), - self, - ); - - let expression = Expression { lhs, op, rhs, code_regions: code_regions.to_owned() }; - let slot = &mut self.expressions[expression_id]; - match slot { - None => *slot = Some(expression), - // If this expression ID slot has already been filled, it should - // contain identical information. - Some(ref previous_expression) => assert_eq!( - previous_expression, &expression, - "add_counter_expression: expression for id changed" - ), - } + pub(crate) fn mark_expression_id_seen(&mut self, id: ExpressionId) { + self.expressions_seen.insert(id); } - /// Adds regions that will be marked as "unreachable", with a constant "zero counter". - #[instrument(level = "debug", skip(self))] - pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) { - assert!(!code_regions.is_empty(), "unreachable regions always have code regions"); - self.unreachable_regions.extend_from_slice(code_regions); - } - - /// Perform some simplifications to make the final coverage mappings - /// slightly smaller. + /// Identify expressions that will always have a value of zero, and note + /// their IDs in [`ZeroExpressions`]. Mappings that refer to a zero expression + /// can instead become mappings to a constant zero value. /// /// This method mainly exists to preserve the simplifications that were /// already being performed by the Rust-side expression renumbering, so that /// the resulting coverage mappings don't get worse. - pub(crate) fn simplify_expressions(&mut self) { + fn identify_zero_expressions(&self) -> ZeroExpressions { // The set of expressions that either were optimized out entirely, or // have zero as both of their operands, and will therefore always have // a value of zero. Other expressions that refer to these as operands - // can have those operands replaced with `Operand::Zero`. + // can have those operands replaced with `CovTerm::Zero`. let mut zero_expressions = FxIndexSet::default(); - // For each expression, perform simplifications based on lower-numbered - // expressions, and then update the set of always-zero expressions if - // necessary. + // Simplify a copy of each expression based on lower-numbered expressions, + // and then update the set of always-zero expressions if necessary. // (By construction, expressions can only refer to other expressions - // that have lower IDs, so one simplification pass is sufficient.) - for (id, maybe_expression) in self.expressions.iter_enumerated_mut() { - let Some(expression) = maybe_expression else { - // If an expression is missing, it must have been optimized away, + // that have lower IDs, so one pass is sufficient.) + for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { + if !self.expressions_seen.contains(id) { + // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. zero_expressions.insert(id); continue; + } + + // We don't need to simplify the actual expression data in the + // expressions list; we can just simplify a temporary copy and then + // use that to update the set of always-zero expressions. + let Expression { mut lhs, op, mut rhs } = *expression; + + // If an expression has an operand that is also an expression, the + // operand's ID must be strictly lower. This is what lets us find + // all zero expressions in one pass. + let assert_operand_expression_is_lower = |operand_id: ExpressionId| { + assert!( + operand_id < id, + "Operand {operand_id:?} should be less than {id:?} in {expression:?}", + ) }; // If an operand refers to an expression that is always zero, then - // that operand can be replaced with `Operand::Zero`. - let maybe_set_operand_to_zero = |operand: &mut Operand| match &*operand { - Operand::Expression(id) if zero_expressions.contains(id) => { - *operand = Operand::Zero; + // that operand can be replaced with `CovTerm::Zero`. + let maybe_set_operand_to_zero = |operand: &mut CovTerm| match *operand { + CovTerm::Expression(id) => { + assert_operand_expression_is_lower(id); + if zero_expressions.contains(&id) { + *operand = CovTerm::Zero; + } } _ => (), }; - maybe_set_operand_to_zero(&mut expression.lhs); - maybe_set_operand_to_zero(&mut expression.rhs); + maybe_set_operand_to_zero(&mut lhs); + maybe_set_operand_to_zero(&mut rhs); // Coverage counter values cannot be negative, so if an expression // involves subtraction from zero, assume that its RHS must also be zero. // (Do this after simplifications that could set the LHS to zero.) - if let Expression { lhs: Operand::Zero, op: Op::Subtract, .. } = expression { - expression.rhs = Operand::Zero; + if lhs == CovTerm::Zero && op == Op::Subtract { + rhs = CovTerm::Zero; } // After the above simplifications, if both operands are zero, then // we know that this expression is always zero too. - if let Expression { lhs: Operand::Zero, rhs: Operand::Zero, .. } = expression { + if lhs == CovTerm::Zero && rhs == CovTerm::Zero { zero_expressions.insert(id); } } + + ZeroExpressions(zero_expressions) } /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. pub fn source_hash(&self) -> u64 { - self.source_hash + if self.is_used { self.function_coverage_info.function_source_hash } else { 0 } } /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their @@ -204,91 +177,80 @@ impl<'tcx> FunctionCoverage<'tcx> { pub fn get_expressions_and_counter_regions( &self, ) -> (Vec, impl Iterator) { - assert!( - self.source_hash != 0 || !self.is_used, - "No counters provided the source_hash for used function: {:?}", - self.instance - ); + let zero_expressions = self.identify_zero_expressions(); - let counter_expressions = self.counter_expressions(); + let counter_expressions = self.counter_expressions(&zero_expressions); // Expression IDs are indices into `self.expressions`, and on the LLVM // side they will be treated as indices into `counter_expressions`, so // the two vectors should correspond 1:1. - assert_eq!(self.expressions.len(), counter_expressions.len()); + assert_eq!(self.function_coverage_info.expressions.len(), counter_expressions.len()); - let counter_regions = self.counter_regions(); - let expression_regions = self.expression_regions(); - let unreachable_regions = self.unreachable_regions(); + let counter_regions = self.counter_regions(zero_expressions); - let counter_regions = - counter_regions.chain(expression_regions.into_iter().chain(unreachable_regions)); (counter_expressions, counter_regions) } - fn counter_regions(&self) -> impl Iterator { - self.counters - .iter_enumerated() - // Filter out counter IDs that we never saw during MIR traversal. - // This can happen if a counter was optimized out by MIR transforms - // (and replaced with `CoverageKind::Unreachable` instead). - .filter_map(|(id, maybe_code_regions)| Some((id, maybe_code_regions.as_ref()?))) - .flat_map(|(id, code_regions)| { - let counter = Counter::counter_value_reference(id); - code_regions.iter().map(move |region| (counter, region)) - }) - } - /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. - fn counter_expressions(&self) -> Vec { + fn counter_expressions(&self, zero_expressions: &ZeroExpressions) -> Vec { // We know that LLVM will optimize out any unused expressions before // producing the final coverage map, so there's no need to do the same // thing on the Rust side unless we're confident we can do much better. // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.) - self.expressions + let counter_from_operand = |operand: CovTerm| match operand { + CovTerm::Expression(id) if zero_expressions.contains(id) => Counter::ZERO, + _ => Counter::from_term(operand), + }; + + self.function_coverage_info + .expressions .iter() - .map(|expression| match expression { - None => { - // This expression ID was allocated, but we never saw the - // actual expression, so it must have been optimized out. - // Replace it with a dummy expression, and let LLVM take - // care of omitting it from the expression list. - CounterExpression::DUMMY - } - &Some(Expression { lhs, op, rhs, .. }) => { - // Convert the operands and operator as normal. - CounterExpression::new( - Counter::from_operand(lhs), - match op { - Op::Add => ExprKind::Add, - Op::Subtract => ExprKind::Subtract, - }, - Counter::from_operand(rhs), - ) - } + .map(|&Expression { lhs, op, rhs }| CounterExpression { + lhs: counter_from_operand(lhs), + kind: match op { + Op::Add => ExprKind::Add, + Op::Subtract => ExprKind::Subtract, + }, + rhs: counter_from_operand(rhs), }) .collect::>() } - fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> { - // Find all of the expression IDs that weren't optimized out AND have - // one or more attached code regions, and return the corresponding - // mappings as counter/region pairs. - self.expressions - .iter_enumerated() - .filter_map(|(id, maybe_expression)| { - let code_regions = &maybe_expression.as_ref()?.code_regions; - Some((id, code_regions)) - }) - .flat_map(|(id, code_regions)| { - let counter = Counter::expression(id); - code_regions.iter().map(move |code_region| (counter, code_region)) - }) - .collect::>() - } + /// Converts this function's coverage mappings into an intermediate form + /// that will be used by `mapgen` when preparing for FFI. + fn counter_regions( + &self, + zero_expressions: ZeroExpressions, + ) -> impl Iterator { + // Historically, mappings were stored directly in counter/expression + // statements in MIR, and MIR optimizations would sometimes remove them. + // That's mostly no longer true, so now we detect cases where that would + // have happened, and zero out the corresponding mappings here instead. + let counter_for_term = move |term: CovTerm| { + let force_to_zero = match term { + CovTerm::Counter(id) => !self.counters_seen.contains(id), + CovTerm::Expression(id) => zero_expressions.contains(id), + CovTerm::Zero => false, + }; + if force_to_zero { Counter::ZERO } else { Counter::from_term(term) } + }; - fn unreachable_regions(&self) -> impl Iterator { - self.unreachable_regions.iter().map(|region| (Counter::ZERO, region)) + self.function_coverage_info.mappings.iter().map(move |mapping| { + let &Mapping { term, ref code_region } = mapping; + let counter = counter_for_term(term); + (counter, code_region) + }) + } +} + +/// Set of expression IDs that are known to always evaluate to zero. +/// Any mapping or expression operand that refers to these expressions can have +/// that reference replaced with a constant zero value. +struct ZeroExpressions(FxIndexSet); + +impl ZeroExpressions { + fn contains(&self, id: ExpressionId) -> bool { + self.0.contains(&id) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d58e95fcd363..411620c9e493 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -10,9 +10,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::CodeRegion; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; /// Generates and exports the Coverage Map. @@ -60,10 +59,8 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // Encode coverage mappings and generate function records let mut function_data = Vec::new(); - for (instance, mut function_coverage) in function_coverage_map { + for (instance, function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); - function_coverage.simplify_expressions(); - let function_coverage = function_coverage; let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); @@ -170,10 +167,11 @@ fn encode_mappings_for_function( let mut virtual_file_mapping = IndexVec::::new(); let mut mapping_regions = Vec::with_capacity(counter_regions.len()); - // Sort the list of (counter, region) mapping pairs by region, so that they - // can be grouped by filename. Prepare file IDs for each filename, and - // prepare the mapping data so that we can pass it through FFI to LLVM. - counter_regions.sort_by_key(|(_counter, region)| *region); + // Sort and group the list of (counter, region) mapping pairs by filename. + // (Preserve any further ordering imposed by `FunctionCoverage`.) + // Prepare file IDs for each filename, and prepare the mapping data so that + // we can pass it through FFI to LLVM. + counter_regions.sort_by_key(|(_counter, region)| region.file_name); for counter_regions_for_file in counter_regions.group_by(|(_, a), (_, b)| a.file_name == b.file_name) { @@ -331,16 +329,14 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) { for non_codegenned_def_id in eligible_def_ids.into_iter().filter(|id| !codegenned_def_ids.contains(id)) { - let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id); - - // If a function is marked `#[coverage(off)]`, then skip generating a - // dead code stub for it. - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { - debug!("skipping unused fn marked #[coverage(off)]: {:?}", non_codegenned_def_id); + // Skip any function that didn't have coverage data added to it by the + // coverage instrumentor. + let body = tcx.instance_mir(ty::InstanceDef::Item(non_codegenned_def_id)); + let Some(function_coverage_info) = body.function_coverage_info.as_deref() else { continue; - } + }; debug!("generating unused fn: {:?}", non_codegenned_def_id); - cx.define_unused_fn(non_codegenned_def_id); + cx.define_unused_fn(non_codegenned_def_id, function_coverage_info); } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index dd2ce9b525b7..204a73b788a6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -16,7 +16,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::coverage::{CounterId, CoverageKind, FunctionCoverageInfo}; use rustc_middle::mir::Coverage; use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; @@ -88,44 +88,63 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// For used/called functions, the coverageinfo was already added to the /// `function_coverage_map` (keyed by function `Instance`) during codegen. /// But in this case, since the unused function was _not_ previously - /// codegenned, collect the coverage `CodeRegion`s from the MIR and add - /// them. Since the function is never called, all of its `CodeRegion`s can be - /// added as `unreachable_region`s. - fn define_unused_fn(&self, def_id: DefId) { + /// codegenned, collect the function coverage info from MIR and add an + /// "unused" entry to the function coverage map. + fn define_unused_fn(&self, def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo) { let instance = declare_unused_fn(self, def_id); codegen_unused_fn_and_counter(self, instance); - add_unused_function_coverage(self, instance, def_id); + add_unused_function_coverage(self, instance, function_coverage_info); } } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + #[instrument(level = "debug", skip(self))] fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { + // Our caller should have already taken care of inlining subtleties, + // so we can assume that counter/expression IDs in this coverage + // statement are meaningful for the given instance. + // + // (Either the statement was not inlined and directly belongs to this + // instance, or it was inlined *from* this instance.) + let bx = self; + let Some(function_coverage_info) = + bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref() + else { + debug!("function has a coverage statement but no coverage info"); + return; + }; + let Some(coverage_context) = bx.coverage_context() else { return }; let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); let func_coverage = coverage_map .entry(instance) - .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance)); + .or_insert_with(|| FunctionCoverage::new(instance, function_coverage_info)); - let Coverage { kind, code_regions } = coverage; + let Coverage { kind } = coverage; match *kind { - CoverageKind::Counter { function_source_hash, id } => { - debug!( - "ensuring function source hash is set for instance={:?}; function_source_hash={}", - instance, function_source_hash, - ); - func_coverage.set_function_source_hash(function_source_hash); - func_coverage.add_counter(id, code_regions); + CoverageKind::CounterIncrement { id } => { + func_coverage.mark_counter_id_seen(id); // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`, // as that needs an exclusive borrow. drop(coverage_map); - let coverageinfo = bx.tcx().coverageinfo(instance.def); + // The number of counters passed to `llvm.instrprof.increment` might + // be smaller than the number originally inserted by the instrumentor, + // if some high-numbered counters were removed by MIR optimizations. + // If so, LLVM's profiler runtime will use fewer physical counters. + let num_counters = + bx.tcx().coverage_ids_info(instance.def).max_counter_id.as_u32() + 1; + assert!( + num_counters as usize <= function_coverage_info.num_counters, + "num_counters disagreement: query says {num_counters} but function info only has {}", + function_coverage_info.num_counters + ); let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); + let hash = bx.const_u64(function_coverage_info.function_source_hash); + let num_counters = bx.const_u32(num_counters); let index = bx.const_u32(id.as_u32()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", @@ -133,11 +152,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { ); bx.instrprof_increment(fn_name, hash, num_counters, index); } - CoverageKind::Expression { id, lhs, op, rhs } => { - func_coverage.add_counter_expression(id, lhs, op, rhs, code_regions); - } - CoverageKind::Unreachable => { - func_coverage.add_unreachable_regions(code_regions); + CoverageKind::ExpressionUsed { id } => { + func_coverage.mark_expression_id_seen(id); } } } @@ -200,15 +216,11 @@ fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Insta fn add_unused_function_coverage<'tcx>( cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, - def_id: DefId, + function_coverage_info: &'tcx FunctionCoverageInfo, ) { - let tcx = cx.tcx; - - let mut function_coverage = FunctionCoverage::unused(tcx, instance); - for &code_region in tcx.covered_code_regions(def_id) { - let code_region = std::slice::from_ref(code_region); - function_coverage.add_unreachable_regions(code_region); - } + // An unused function's mappings will automatically be rewritten to map to + // zero, because none of its counters/expressions are marked as seen. + let function_coverage = FunctionCoverage::unused(instance, function_coverage_info); if let Some(coverage_context) = cx.coverage_context() { coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 5b31738e4e18..d7c7e2798496 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1235,6 +1235,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. + /// + /// The result must be used immediately; it is not allowed to convert + /// the returned data back into a `Pointer` and store that in machine state. + /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and + /// we don't have an operation to turn it back into `M::Provenance`.) pub fn ptr_try_get_alloc_id( &self, ptr: Pointer>, @@ -1253,6 +1258,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). + /// + /// The result must be used immediately; it is not allowed to convert + /// the returned data back into a `Pointer` and store that in machine state. + /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and + /// we don't have an operation to turn it back into `M::Provenance`.) #[inline(always)] pub fn ptr_get_alloc_id( &self, diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index a924afda6f07..54eb14ae8fc4 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::ty::{ self, - print::{PrettyPrinter, Print, Printer}, + print::{PrettyPrinter, Print, PrintError, Printer}, GenericArg, GenericArgKind, Ty, TyCtxt, }; use std::fmt::Write; @@ -14,23 +14,15 @@ struct AbsolutePathPrinter<'tcx> { } impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = std::fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Types without identity. ty::Bool @@ -68,18 +60,18 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -88,17 +80,17 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_qualified(self_ty, trait_ref) } fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -114,9 +106,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; write!(self.path, "::{}", disambiguated_data.data).unwrap(); @@ -126,9 +118,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); @@ -144,9 +136,9 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -160,8 +152,8 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; self = f(self)?; diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs deleted file mode 100644 index e3fcaccb1bd5..000000000000 --- a/compiler/rustc_data_structures/src/functor.rs +++ /dev/null @@ -1,116 +0,0 @@ -use rustc_index::{Idx, IndexVec}; -use std::{mem, rc::Rc, sync::Arc}; - -pub trait IdFunctor: Sized { - type Inner; - - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result; -} - -impl IdFunctor for Box { - type Inner = T; - - #[inline] - fn try_map_id(self, mut f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - let raw = Box::into_raw(self); - Ok(unsafe { - // SAFETY: The raw pointer points to a valid value of type `T`. - let value = raw.read(); - // SAFETY: Converts `Box` to `Box>` which is the - // inverse of `Box::assume_init()` and should be safe. - let raw: Box> = Box::from_raw(raw.cast()); - // SAFETY: Write the mapped value back into the `Box`. - Box::write(raw, f(value)?) - }) - } -} - -impl IdFunctor for Vec { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - self.into_iter().map(f).collect() - } -} - -impl IdFunctor for Box<[T]> { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - Vec::from(self).try_map_id(f).map(Into::into) - } -} - -impl IdFunctor for IndexVec { - type Inner = T; - - #[inline] - fn try_map_id(self, f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - self.raw.try_map_id(f).map(IndexVec::from_raw) - } -} - -macro_rules! rc { - ($($rc:ident),+) => {$( - impl IdFunctor for $rc { - type Inner = T; - - #[inline] - fn try_map_id(mut self, mut f: F) -> Result - where - F: FnMut(Self::Inner) -> Result, - { - // We merely want to replace the contained `T`, if at all possible, - // so that we don't needlessly allocate a new `$rc` or indeed clone - // the contained type. - unsafe { - // First step is to ensure that we have a unique reference to - // the contained type, which `$rc::make_mut` will accomplish (by - // allocating a new `$rc` and cloning the `T` only if required). - // This is done *before* casting to `$rc>` so that - // panicking during `make_mut` does not leak the `T`. - $rc::make_mut(&mut self); - - // Casting to `$rc>` is safe because `ManuallyDrop` - // is `repr(transparent)`. - let ptr = $rc::into_raw(self).cast::>(); - let mut unique = $rc::from_raw(ptr); - - // Call to `$rc::make_mut` above guarantees that `unique` is the - // sole reference to the contained value, so we can avoid doing - // a checked `get_mut` here. - let slot = $rc::get_mut_unchecked(&mut unique); - - // Semantically move the contained type out from `unique`, fold - // it, then move the folded value back into `unique`. Should - // folding fail, `ManuallyDrop` ensures that the "moved-out" - // value is not re-dropped. - let owned = mem::ManuallyDrop::take(slot); - let folded = f(owned)?; - *slot = mem::ManuallyDrop::new(folded); - - // Cast back to `$rc`. - Ok($rc::from_raw($rc::into_raw(unique).cast())) - } - } - } - )+}; -} - -rc! { Rc, Arc } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 420f7c4f17f1..9511f1700e10 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,7 +10,6 @@ #![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] -#![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(cell_leak)] #![feature(core_intrinsics)] @@ -21,15 +20,12 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(type_alias_impl_trait)] -#![feature(new_uninit)] #![feature(lazy_cell)] #![feature(rustc_attrs)] #![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] -#![feature(vec_into_raw_parts)] #![feature(allocator_api)] -#![feature(get_mut_unchecked)] #![feature(lint_reasons)] #![feature(unwrap_infallible)] #![feature(strict_provenance)] @@ -65,7 +61,6 @@ pub mod binary_search_util; pub mod captures; pub mod flat_map_in_place; pub mod flock; -pub mod functor; pub mod fx; pub mod graph; pub mod intern; diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 4894312b0d21..d931a8dab9b8 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -52,7 +52,7 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" -time = { version = "0.3", default-features = false, features = ["formatting", ] } +time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b0c95e1bd205..7e4a7d93210e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -62,7 +62,6 @@ use std::str; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::OnceLock; use std::time::{Instant, SystemTime}; -use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; #[allow(unused_macros)] @@ -1185,7 +1184,11 @@ fn print_flag_list( /// /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. -fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option { +/// +/// This does not need to be `pub` for rustc itself, but @chaosite needs it to +/// be public when using rustc as a library, see +/// +pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option { if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. @@ -1307,7 +1310,13 @@ fn ice_path() -> &'static Option { None => std::env::current_dir().unwrap_or_default(), }; let now: OffsetDateTime = SystemTime::now().into(); - let file_now = now.format(&Rfc3339).unwrap_or_default(); + let file_now = now + .format( + // Don't use a standard datetime format because Windows doesn't support `:` in paths + &time::format_description::parse("[year]-[month]-[day]T[hour]_[minute]_[second]") + .unwrap(), + ) + .unwrap_or_default(); let pid = std::process::id(); path.push(format!("rustc-ice-{file_now}-{pid}.txt")); Some(path) diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index f5a6585b5c68..60b8e1e3786d 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_fluent_macro" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 059dfc604500..711da6db5acc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -448,7 +448,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { debug!(?args_trait_ref_and_assoc_item); - tcx.mk_alias_ty(assoc_item.def_id, args_trait_ref_and_assoc_item) + ty::AliasTy::new(tcx, assoc_item.def_id, args_trait_ref_and_assoc_item) }) }; diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 9e18767a7c3e..889bc2ea4329 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -437,7 +437,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self); + ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); let term = pred.skip_binder().term; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6bcf33a1f6d8..2fcb45ef8aa1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -916,7 +916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. - let alias_ty = tcx.mk_alias_ty(did, args); + let alias_ty = ty::AliasTy::new(tcx, did, args); Ty::new_alias(tcx, ty::Weak, alias_ty) } else { tcx.at(span).type_of(did).instantiate(tcx, args) @@ -1018,7 +1018,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.span_suggestions( span, - "use the fully-qualified path", + "use fully-qualified syntax", suggestions, Applicability::MachineApplicable, ); @@ -1091,7 +1091,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) }); - let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { + let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next()) + { (Some(bound), _) => (bound, matching_candidates.next()), (None, Some(bound)) => (bound, const_candidates.next()), (None, None) => { @@ -1107,6 +1108,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; debug!(?bound); + // look for a candidate that is not the same as our first bound, disregarding + // whether the bound is const. + while let Some(mut bound2) = next_cand { + debug!(?bound2); + let tcx = self.tcx(); + if bound2.bound_vars() != bound.bound_vars() { + break; + } + + let generics = tcx.generics_of(bound.def_id()); + let Some(host_index) = generics.host_effect_index else { break }; + + // always return the bound that contains the host param. + if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() { + (bound, bound2) = (bound2, bound); + } + + let unconsted_args = bound + .skip_binder() + .args + .iter() + .enumerate() + .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); + + if unconsted_args.eq(bound2.skip_binder().args.iter()) { + next_cand = matching_candidates.next().or_else(|| const_candidates.next()); + } else { + break; + } + } + if let Some(bound2) = next_cand { debug!(?bound2); @@ -1158,7 +1190,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { err.span_suggestion_verbose( span.with_hi(assoc_name.span.lo()), - "use fully qualified syntax to disambiguate", + "use fully-qualified syntax to disambiguate", format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()), Applicability::MaybeIncorrect, ); @@ -1686,7 +1718,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(args.into_iter().skip(parent_args.len())), ); - let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, args)); + let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); return Ok(Some((ty, assoc_item))); } diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 1d9ae2b9cb73..b6688e0ce29e 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -43,6 +43,34 @@ impl<'tcx> Bounds<'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, span: Span, polarity: ty::ImplPolarity, + ) { + self.push_trait_bound_inner(tcx, trait_ref, span, polarity); + + // push a non-const (`host = true`) version of the bound if it is `~const`. + if tcx.features().effects + && let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index + && trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_ + { + let generics = tcx.generics_of(trait_ref.def_id()); + let Some(host_index) = generics.host_effect_index else { return }; + let trait_ref = trait_ref.map_bound(|mut trait_ref| { + trait_ref.args = + tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| { + if host_index == n { tcx.consts.true_.into() } else { arg } + })); + trait_ref + }); + + self.push_trait_bound_inner(tcx, trait_ref, span, polarity); + } + } + + fn push_trait_bound_inner( + &mut self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + polarity: ty::ImplPolarity, ) { self.clauses.push(( trait_ref diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2eb9b773b2ef..a1470cc69c30 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2286,7 +2286,7 @@ pub(super) fn check_type_bounds<'tcx>( _ => predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args), + projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args), term: normalize_impl_ty.into(), }, bound_vars, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 1b38f77654cf..104da581e019 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate}; use rustc_span::symbol::Ident; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus @@ -38,11 +38,38 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // an obligation and instead be skipped. Otherwise we'd use // `tcx.def_span(def_id);` 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).to_predicate(tcx), + let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) { + // when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound, + // because only implementing `Self: Trait<.., false>` is currently not possible. + Some(( + ty::TraitRef::new( + tcx, + def_id, + ty::GenericArgs::for_item(tcx, def_id, |param, _| { + if param.is_host_effect() { + tcx.consts.true_.into() + } else { + tcx.mk_param_from_def(param) + } + }), + ) + .to_predicate(tcx), span, - )))); + )) + } else { + None + }; + result.predicates = tcx.arena.alloc_from_iter( + result + .predicates + .iter() + .copied() + .chain(std::iter::once(( + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), + span, + ))) + .chain(non_const_bound), + ); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index ce91d023a0ae..0666eeee4d38 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_hir_typeck" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 512d73fc1036..78d30f3aa12e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .sess .source_map() .is_multiline(call_expr.span.with_lo(callee_expr.span.hi())) - && call_expr.span.ctxt() == callee_expr.span.ctxt(); + && call_expr.span.eq_ctxt(callee_expr.span); if call_is_multiline { err.span_suggestion( callee_expr.span.shrink_to_hi(), @@ -786,8 +786,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.consts.false_ } Some(hir::ConstContext::ConstFn) => { - let args = ty::GenericArgs::identity_for_item(tcx, context); - args.host_effect_param().expect("ConstContext::Maybe must have host effect param") + let host_idx = tcx + .generics_of(context) + .host_effect_index + .expect("ConstContext::Maybe must have host effect param"); + ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx) } None => tcx.consts.true_, }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 4a245d30c8e3..7677d6f953b6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -221,14 +221,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + // HACK(eddyb) should get the original `Span`. + let span = tcx.def_span(def_id); ty::GenericPredicates { parent: None, predicates: tcx.arena.alloc_from_iter( self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { - // HACK(eddyb) should get the original `Span`. - let span = tcx.def_span(def_id); Some((predicate, span)) } _ => None, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8ea0280c5e9b..6b0dc73d49c6 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -674,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self); + ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); let term = pred.skip_binder().term; @@ -1260,6 +1260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Dynamic limit to avoid hiding just one candidate, which is silly. let limit = if sources.len() == 5 { 5 } else { 4 }; + let mut suggs = vec![]; for (idx, source) in sources.iter().take(limit).enumerate() { match *source { CandidateSource::Impl(impl_did) => { @@ -1322,7 +1323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, + ty::AssocKind::Const | ty::AssocKind::Type => impl_ty, ty::AssocKind::Fn => self .tcx .fn_sig(item.def_id) @@ -1334,19 +1335,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .copied() .unwrap_or(rcvr_ty), }; - print_disambiguation_help( + if let Some(sugg) = print_disambiguation_help( item_name, args, err, path, ty, + Some(impl_ty), item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, idx, self.tcx.sess.source_map(), item.fn_has_self_parameter, - ); + ) { + suggs.push(sugg); + } } } CandidateSource::Trait(trait_did) => { @@ -1370,23 +1374,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(sugg_span) = sugg_span { let path = self.tcx.def_path_str(trait_did); - print_disambiguation_help( + if let Some(sugg) = print_disambiguation_help( item_name, args, err, path, rcvr_ty, + None, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, idx, self.tcx.sess.source_map(), item.fn_has_self_parameter, - ); + ) { + suggs.push(sugg); + } } } } } + if !suggs.is_empty() && let Some(span) = sugg_span { + err.span_suggestions( + span.with_hi(item_name.span.lo()), + "use fully-qualified syntax to disambiguate", + suggs, + Applicability::MachineApplicable, + ); + } if sources.len() > limit { err.note(format!("and {} others", sources.len() - limit)); } @@ -3146,52 +3161,51 @@ fn print_disambiguation_help<'tcx>( err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, + impl_self_ty: Option>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, candidate: Option, source_map: &source_map::SourceMap, fn_has_self_parameter: bool, -) { - let mut applicability = Applicability::MachineApplicable; - let (span, sugg) = if let ( - ty::AssocKind::Fn, - Some(MethodCallComponents { receiver, args, .. }), - ) = (kind, args) - { - let args = format!( - "({}{})", - rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), - std::iter::once(receiver) - .chain(args.iter()) - .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::>() - .join(", "), - ); - let trait_name = if !fn_has_self_parameter { - format!("<{rcvr_ty} as {trait_name}>") +) -> Option { + Some( + if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) + { + let args = format!( + "({}{})", + rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), + std::iter::once(receiver) + .chain(args.iter()) + .map(|arg| source_map + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { "_".to_owned() })) + .collect::>() + .join(", "), + ); + let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { + format!("<{impl_self_ty} as {trait_name}>") } else { trait_name }; - (span, format!("{trait_name}::{item_name}{args}")) - } else { - (span.with_hi(item_name.span.lo()), format!("<{rcvr_ty} as {trait_name}>::")) - }; - err.span_suggestion_verbose( - span, - format!( - "disambiguate the {} for {}", - def_kind_descr, - if let Some(candidate) = candidate { - format!("candidate #{candidate}") - } else { - "the candidate".to_string() - }, - ), - sugg, - applicability, - ); + err.span_suggestion_verbose( + span, + format!( + "disambiguate the {def_kind_descr} for {}", + if let Some(candidate) = candidate { + format!("candidate #{candidate}") + } else { + "the candidate".to_string() + }, + ), + format!("{trait_name}::{item_name}{args}"), + Applicability::HasPlaceholders, + ); + return None; + } else if let Some(impl_self_ty) = impl_self_ty { + format!("<{impl_self_ty} as {trait_name}>::") + } else { + format!("{trait_name}::") + }, + ) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d35b318e258d..496bb1766a71 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -67,7 +67,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_middle::dep_graph::DepContext; -use rustc_middle::ty::print::with_forced_trimmed_paths; +use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, @@ -580,76 +580,68 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { struct AbsolutePathPrinter<'tcx> { tcx: TyCtxt<'tcx>, + segments: Vec, } - struct NonTrivialPath; - impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = NonTrivialPath; - - type Path = Vec; - type Region = !; - type Type = !; - type DynExistential = !; - type Const = !; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { - Err(NonTrivialPath) + fn print_region(self, _region: ty::Region<'_>) -> Result { + Err(fmt::Error) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { - Err(NonTrivialPath) + fn print_type(self, _ty: Ty<'tcx>) -> Result { + Err(fmt::Error) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { - Err(NonTrivialPath) + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + Err(fmt::Error) } - fn path_crate(self, cnum: CrateNum) -> Result { - Ok(vec![self.tcx.crate_name(cnum).to_string()]) + fn path_crate(mut self, cnum: CrateNum) -> Result { + self.segments = vec![self.tcx.crate_name(cnum).to_string()]; + Ok(self) } fn path_qualified( self, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } fn path_append_impl( self, - _print_prefix: impl FnOnce(Self) -> Result, + _print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, _self_ty: Ty<'tcx>, _trait_ref: Option>, - ) -> Result { - Err(NonTrivialPath) + ) -> Result { + Err(fmt::Error) } fn path_append( - self, - print_prefix: impl FnOnce(Self) -> Result, + mut self, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { - let mut path = print_prefix(self)?; - path.push(disambiguated_data.to_string()); - Ok(path) + ) -> Result { + self = print_prefix(self)?; + self.segments.push(disambiguated_data.to_string()); + Ok(self) } fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } @@ -659,12 +651,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // are from a local module we could have false positives, e.g. // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; if did1.krate != did2.krate { - let abs_path = - |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]); + let abs_path = |def_id| { + AbsolutePathPrinter { tcx: self.tcx, segments: vec![] } + .print_def_path(def_id, &[]) + .map(|p| p.segments) + }; // We compare strings because DefPath can be different // for imported and non-imported crates - let same_path = || -> Result<_, NonTrivialPath> { + let same_path = || -> Result<_, PrintError> { Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) || abs_path(did1)? == abs_path(did2)?) }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 4aec28b051f1..d6a3bc32cc93 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -28,7 +28,7 @@ pub struct Highlighted<'tcx, T> { impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) @@ -43,7 +43,7 @@ impl<'tcx, T> Highlighted<'tcx, T> { impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 24767b0bda6e..3da6d8a89e10 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -85,8 +85,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { let p_def_id = tcx.generics_of(body_owner_def_id).type_param(p, tcx).def_id; let p_span = tcx.def_span(p_def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } let hir = tcx.hir(); let mut note = true; @@ -168,8 +173,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } diag.help("type parameters must be constrained to match other types"); if tcx.sess.teach(&diag.get_code().unwrap()) { @@ -209,7 +219,7 @@ impl Trait for X { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, "expected this type parameter"); } diag.help(format!( "every closure has a distinct type and so could not always match the \ @@ -219,8 +229,13 @@ impl Trait for X { (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; if !sp.contains(p_span) { - diag.span_label(p_span, "this type parameter"); + diag.span_label(p_span, format!("{expected}this type parameter")); } } (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) @@ -341,39 +356,48 @@ impl Trait for X { let tcx = self.tcx; let assoc = tcx.associated_item(proj_ty.def_id); let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx); - if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) { - if let Some(hir_generics) = item.generics() { - // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. - // This will also work for `impl Trait`. - let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() { - let generics = tcx.generics_of(body_owner_def_id); - generics.type_param(param_ty, tcx).def_id - } else { - return false; - }; - let Some(def_id) = def_id.as_local() else { - return false; - }; + let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else { + return false; + }; + let Some(hir_generics) = item.generics() else { + return false; + }; + // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. + // This will also work for `impl Trait`. + let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() { + let generics = tcx.generics_of(body_owner_def_id); + generics.type_param(param_ty, tcx).def_id + } else { + return false; + }; + let Some(def_id) = def_id.as_local() else { + return false; + }; - // First look in the `where` clause, as this might be - // `fn foo(x: T) where T: Trait`. - for pred in hir_generics.bounds_for_param(def_id) { - if self.constrain_generic_bound_associated_type_structured_suggestion( - diag, - &trait_ref, - pred.bounds, - assoc, - assoc_args, - ty, - &msg, - false, - ) { - return true; - } - } + // First look in the `where` clause, as this might be + // `fn foo(x: T) where T: Trait`. + for pred in hir_generics.bounds_for_param(def_id) { + if self.constrain_generic_bound_associated_type_structured_suggestion( + diag, + &trait_ref, + pred.bounds, + assoc, + assoc_args, + ty, + &msg, + false, + ) { + return true; } } - false + // If associated item, look to constrain the params of the trait/impl. + let hir_id = match item { + hir::Node::ImplItem(item) => item.hir_id(), + hir::Node::TraitItem(item) => item.hir_id(), + _ => return false, + }; + let parent = tcx.hir().get_parent_item(hir_id).def_id; + self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty) } /// An associated type was expected and a different type was found. @@ -426,21 +450,26 @@ impl Trait for X { let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. }); let assoc = tcx.associated_item(proj_ty.def_id); - if !callable_scope || impl_comparison { + if impl_comparison { // We do not want to suggest calling functions when the reason of the - // type error is a comparison of an `impl` with its `trait` or when the - // scope is outside of a `Body`. + // type error is a comparison of an `impl` with its `trait`. } else { - // If we find a suitable associated function that returns the expected type, we don't - // want the more general suggestion later in this method about "consider constraining - // the associated type or calling a method that returns the associated type". - let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type( - diag, - assoc.container_id(tcx), - current_method_ident, - proj_ty.def_id, - values.expected, - ); + let point_at_assoc_fn = if callable_scope + && self.point_at_methods_that_satisfy_associated_type( + diag, + assoc.container_id(tcx), + current_method_ident, + proj_ty.def_id, + values.expected, + ) { + // If we find a suitable associated function that returns the expected type, we + // don't want the more general suggestion later in this method about "consider + // constraining the associated type or calling a method that returns the associated + // type". + true + } else { + false + }; // Possibly suggest constraining the associated type to conform to the // found type. if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aeb3177af027..8ffcf1fce9cf 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtx use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::{Cell, RefCell}; use std::fmt; @@ -1422,12 +1422,25 @@ impl<'tcx> InferCtxt<'tcx> { /// This method is idempotent, but it not typically not invoked /// except during the writeback phase. pub fn fully_resolve>>(&self, value: T) -> FixupResult<'tcx, T> { - let value = resolve::fully_resolve(self, value); - assert!( - value.as_ref().map_or(true, |value| !value.has_infer()), - "`{value:?}` is not fully resolved" - ); - value + match resolve::fully_resolve(self, value) { + Ok(value) => { + if value.has_non_region_infer() { + bug!("`{value:?}` is not fully resolved"); + } + if value.has_infer_regions() { + let guar = self + .tcx + .sess + .delay_span_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved")); + Ok(self.tcx.fold_regions(value, |re, _| { + if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } + })) + } else { + Ok(value) + } + } + Err(e) => Err(e), + } } // Instantiates the bound variables in a given binder with fresh inference diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 09df93fcc2fd..1c3a5c360765 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -145,25 +145,7 @@ impl<'tcx> InferCtxt<'tcx> { return None; } } - DefiningAnchor::Bubble => { - if let ty::Alias(ty::Opaque, _) = b.kind() { - // In bubble mode we don't know which of the two opaque types is supposed to have the other - // as a hidden type (both, none or either one of them could be in its defining scope). - let predicate = ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ); - let obligation = traits::Obligation::new( - self.tcx, - cause.clone(), - param_env, - predicate, - ); - let obligations = vec![obligation]; - return Some(Ok(InferOk { value: (), obligations })); - } - } + DefiningAnchor::Bubble => {} DefiningAnchor::Error => return None, }; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3e77a84bf9ef..d2ce77ad5351 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -125,8 +125,13 @@ pub fn parse_cfgspecs( /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { rustc_span::create_default_session_if_not_set_then(move |_| { - let mut check_cfg = CheckCfg::default(); + // If any --check-cfg is passed then exhaustive_values and exhaustive_names + // are enabled by default. + let exhaustive_names = !specs.is_empty(); + let exhaustive_values = !specs.is_empty(); + let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; + let mut old_syntax = None; for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" @@ -142,18 +147,21 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check }; } - let expected_error = || { - error!( - "expected `names(name1, name2, ... nameN)` or \ - `values(name, \"value1\", \"value2\", ... \"valueN\")`" - ) - }; + let expected_error = + || error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`"); match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { Ok(mut parser) => match parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { if let Some(args) = meta_item.meta_item_list() { if meta_item.has_name(sym::names) { + // defaults are flipped for the old syntax + if old_syntax == None { + check_cfg.exhaustive_names = false; + check_cfg.exhaustive_values = false; + } + old_syntax = Some(true); + check_cfg.exhaustive_names = true; for arg in args { if arg.is_word() && arg.ident().is_some() { @@ -167,6 +175,13 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check } } } else if meta_item.has_name(sym::values) { + // defaults are flipped for the old syntax + if old_syntax == None { + check_cfg.exhaustive_names = false; + check_cfg.exhaustive_values = false; + } + old_syntax = Some(true); + if let Some((name, values)) = args.split_first() { if name.is_word() && name.ident().is_some() { let ident = name.ident().expect("multi-segment cfg key"); @@ -216,6 +231,116 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> Check } else { expected_error(); } + } else if meta_item.has_name(sym::cfg) { + old_syntax = Some(false); + + let mut names = Vec::new(); + let mut values: FxHashSet<_> = Default::default(); + + let mut any_specified = false; + let mut values_specified = false; + let mut values_any_specified = false; + + for arg in args { + if arg.is_word() && let Some(ident) = arg.ident() { + if values_specified { + error!("`cfg()` names cannot be after values"); + } + names.push(ident); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if any_specified { + error!("`any()` cannot be specified multiple times"); + } + any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else if arg.has_name(sym::values) + && let Some(args) = arg.meta_item_list() + { + if names.is_empty() { + error!( + "`values()` cannot be specified before the names" + ); + } else if values_specified { + error!( + "`values()` cannot be specified multiple times" + ); + } + values_specified = true; + + for arg in args { + if let Some(LitKind::Str(s, _)) = + arg.lit().map(|lit| &lit.kind) + { + values.insert(Some(s.to_string())); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if values_any_specified { + error!( + "`any()` in `values()` cannot be specified multiple times" + ); + } + values_any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else { + error!( + "`values()` arguments must be string literals or `any()`" + ); + } + } + } else { + error!( + "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" + ); + } + } + + if values.is_empty() && !values_any_specified && !any_specified { + values.insert(None); + } else if !values.is_empty() && values_any_specified { + error!( + "`values()` arguments cannot specify string literals and `any()` at the same time" + ); + } + + if any_specified { + if !names.is_empty() + || !values.is_empty() + || values_any_specified + { + error!("`cfg(any())` can only be provided in isolation"); + } + + check_cfg.exhaustive_names = false; + } else { + for name in names { + check_cfg + .expecteds + .entry(name.to_string()) + .and_modify(|v| match v { + ExpectedValues::Some(v) + if !values_any_specified => + { + v.extend(values.clone()) + } + ExpectedValues::Some(_) => *v = ExpectedValues::Any, + ExpectedValues::Any => {} + }) + .or_insert_with(|| { + if values_any_specified { + ExpectedValues::Any + } else { + ExpectedValues::Some(values.clone()) + } + }); + } + } } else { expected_error(); } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 76131c1ad69b..ffa2667a351e 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -3,6 +3,7 @@ #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(lazy_cell)] +#![feature(let_chains)] #![feature(try_blocks)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7799af370089..ec4fd78994e9 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -770,6 +770,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); + tracked!(cross_crate_inline_threshold, Some(200)); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 2211ac1c8a75..373a8970de83 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_lexer" -version = "0.1.0" +version = "0.0.0" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 197fe6552d79..4c4d2933bf4f 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -494,6 +494,8 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` + lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target .label = target type is set here diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs index 2a49a003da11..512136473617 100644 --- a/compiler/rustc_lint/src/async_fn_in_trait.rs +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -58,7 +58,6 @@ declare_lint! { /// /// /// ```rust - /// # #![feature(return_position_impl_trait_in_trait)] /// use core::future::Future; /// pub trait Trait { /// fn method(&self) -> impl Future + Send { async {} } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3e44e1687864..f6c7f4071dc7 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -677,6 +677,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) { return; } + if def.is_variant_list_non_exhaustive() + || def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive()) + { + return; + } // We shouldn't recommend implementing `Copy` on stateful things, // such as iterators. diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index eb1c6be48e64..1f08db308607 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -31,7 +31,7 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError}; use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt}; use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; @@ -1200,51 +1200,45 @@ impl<'tcx> LateContext<'tcx> { /// } /// ``` pub fn get_def_path(&self, def_id: DefId) -> Vec { - pub struct AbsolutePathPrinter<'tcx> { - pub tcx: TyCtxt<'tcx>, + struct AbsolutePathPrinter<'tcx> { + tcx: TyCtxt<'tcx>, + path: Vec, } impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = !; - - type Path = Vec; - type Region = (); - type Type = (); - type DynExistential = (); - type Const = (); - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { - Ok(()) + fn print_region(self, _region: ty::Region<'_>) -> Result { + Ok(self) } - fn print_type(self, _ty: Ty<'tcx>) -> Result { - Ok(()) + fn print_type(self, _ty: Ty<'tcx>) -> Result { + Ok(self) } fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { - Ok(()) + ) -> Result { + Ok(self) } - fn print_const(self, _ct: ty::Const<'tcx>) -> Result { - Ok(()) + fn print_const(self, _ct: ty::Const<'tcx>) -> Result { + Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { - Ok(vec![self.tcx.crate_name(cnum)]) + fn path_crate(mut self, cnum: CrateNum) -> Result { + self.path = vec![self.tcx.crate_name(cnum)]; + Ok(self) } fn path_qualified( - self, + mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { if let ty::Adt(def, args) = self_ty.kind() { return self.print_def_path(def.did(), args); @@ -1253,24 +1247,25 @@ impl<'tcx> LateContext<'tcx> { // This shouldn't ever be needed, but just in case: with_no_trimmed_paths!({ - Ok(vec![match trait_ref { + self.path = vec![match trait_ref { Some(trait_ref) => Symbol::intern(&format!("{trait_ref:?}")), None => Symbol::intern(&format!("<{self_ty}>")), - }]) + }]; + Ok(self) }) } fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // This shouldn't ever be needed, but just in case: - path.push(match trait_ref { + path.path.push(match trait_ref { Some(trait_ref) => { with_no_trimmed_paths!(Symbol::intern(&format!( "", @@ -1288,9 +1283,9 @@ impl<'tcx> LateContext<'tcx> { fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let mut path = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -1298,20 +1293,23 @@ impl<'tcx> LateContext<'tcx> { return Ok(path); } - path.push(Symbol::intern(&disambiguated_data.data.to_string())); + path.path.push(Symbol::intern(&disambiguated_data.data.to_string())); Ok(path) } fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { print_prefix(self) } } - AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap() + AbsolutePathPrinter { tcx: self.tcx, path: vec![] } + .print_def_path(def_id, &[]) + .unwrap() + .path } /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`. diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index fc2d3d0a2544..2d86129c480c 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -3,14 +3,14 @@ use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, + QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, UntranslatableDiagnosticTrivial, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_hir::def::Res; use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath}; -use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; +use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; @@ -537,3 +537,33 @@ impl LateLintPass<'_> for BadOptAccess { } } } + +declare_tool_lint! { + pub rustc::SPAN_USE_EQ_CTXT, + Allow, + "forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead", + report_in_external_macro: true +} + +declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); + +impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { + if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { + cx.emit_spanned_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag); + } + } + } +} + +fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + match &expr.kind { + ExprKind::MethodCall(..) => cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)), + + _ => false, + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b9e455e6c2a3..d61c59af1e05 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -531,6 +531,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(BadOptAccess)); store.register_lints(&PassByValue::get_lints()); store.register_late_mod_pass(|_| Box::new(PassByValue)); + store.register_lints(&SpanUseEqCtxt::get_lints()); + store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs @@ -548,6 +550,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(EXISTING_DOC_KEYWORD), LintId::of(BAD_OPT_ACCESS), + LintId::of(SPAN_USE_EQ_CTXT), ], ); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 594ef97b3ffb..4eaf8bbf5ded 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -900,6 +900,10 @@ pub struct QueryInstability { pub query: Symbol, } +#[derive(LintDiagnostic)] +#[diag(lint_span_use_eq_ctxt)] +pub struct SpanUseEqCtxtDiag; + #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] pub struct TykindKind { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 96a98393fb28..c8d42937f7bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4449,11 +4449,11 @@ declare_lint! { /// on itself), the blanket impl is not considered to hold for `u8`. This will /// change in a future release. pub COINDUCTIVE_OVERLAP_IN_COHERENCE, - Warn, + Deny, "impls that are not considered to overlap may be considered to \ overlap in the future", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #114040 ", }; } diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index 17651ce95987..6e7e19a24024 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_macros" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 846f8d25025a..d6ceaa8a0914 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1273,6 +1273,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.optimized_mir.get(self, id).is_some() } + fn cross_crate_inlinable(self, id: DefIndex) -> bool { + self.root.tables.cross_crate_inlinable.get(self, id).unwrap_or(false) + } + fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { self.root .tables diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f27eee0d79a5..6b6c0d527425 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -287,6 +287,7 @@ provide! { tcx, def_id, other, cdata, item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } + cross_crate_inlinable => { cdata.cross_crate_inlinable(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_private_dep => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index e949e4670e2c..345b3d5e57f8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1054,7 +1054,7 @@ fn should_encode_mir( || (tcx.sess.opts.output_types.should_codegen() && reachable_set.contains(&def_id) && (generics.requires_monomorphization(tcx) - || tcx.codegen_fn_attrs(def_id).requests_inline())); + || tcx.cross_crate_inlinable(def_id))); // The function has a `const` modifier or is in a `#[const_trait]`. let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) || tcx.is_const_default_method(def_id.to_def_id()); @@ -1623,6 +1623,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EntryBuilder::encode_mir({:?})", def_id); if encode_opt { record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); + self.tables + .cross_crate_inlinable + .set(def_id.to_def_id().index, Some(self.tcx.cross_crate_inlinable(def_id))); record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 42764af52c43..2609767a85c5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -427,6 +427,7 @@ define_tables! { object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, + cross_crate_inlinable: Table, closure_saved_names_of_captured_variables: Table>>, mir_generator_witnesses: Table>>, promoted_mir: Table>>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index bb1320942b07..34118e9e8a33 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -299,6 +299,30 @@ impl FixedSizeEncoding for bool { } } +impl FixedSizeEncoding for Option { + type ByteArray = [u8; 1]; + + #[inline] + fn from_bytes(b: &[u8; 1]) -> Self { + match b[0] { + 0 => Some(false), + 1 => Some(true), + 2 => None, + _ => unreachable!(), + } + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8; 1]) { + debug_assert!(!self.is_default()); + b[0] = match self { + Some(false) => 0, + Some(true) => 1, + None => 2, + }; + } +} + impl FixedSizeEncoding for UnusedGenericParams { type ByteArray = [u8; 4]; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 4e5725876c45..f758c1d5e6f5 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -126,14 +126,6 @@ impl CodegenFnAttrs { } } - /// Returns `true` if `#[inline]` or `#[inline(always)]` is present. - pub fn requests_inline(&self) -> bool { - match self.inline { - InlineAttr::Hint | InlineAttr::Always => true, - InlineAttr::None | InlineAttr::Never => false, - } - } - /// Returns `true` if it looks like this symbol needs to be exported, for example: /// /// * `#[no_mangle]` is present diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index a6d6f6f5df4b..08d377a8695f 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -1,5 +1,6 @@ //! Metadata from source code coverage analysis and instrumentation. +use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_span::Symbol; @@ -8,6 +9,11 @@ use std::fmt::{self, Debug, Formatter}; rustc_index::newtype_index! { /// ID of a coverage counter. Values ascend from 0. /// + /// Before MIR inlining, counter IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] @@ -23,6 +29,11 @@ impl CounterId { rustc_index::newtype_index! { /// ID of a coverage-counter expression. Values ascend from 0. /// + /// Before MIR inlining, expression IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] @@ -35,19 +46,21 @@ impl ExpressionId { pub const START: Self = Self::from_u32(0); } -/// Operand of a coverage-counter expression. +/// Enum that can hold a constant zero value, the ID of an physical coverage +/// counter, or the ID of a coverage-counter expression. /// -/// Operands can be a constant zero value, an actual coverage counter, or another -/// expression. Counter/expression operands are referred to by ID. +/// This was originally only used for expression operands (and named `Operand`), +/// but the zero/counter/expression distinction is also useful for representing +/// the value of code/gap mappings, and the true/false arms of branch mappings. #[derive(Copy, Clone, PartialEq, Eq)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum Operand { +pub enum CovTerm { Zero, Counter(CounterId), Expression(ExpressionId), } -impl Debug for Operand { +impl Debug for CovTerm { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Zero => write!(f, "Zero"), @@ -59,40 +72,31 @@ impl Debug for Operand { #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CoverageKind { - Counter { - function_source_hash: u64, - /// ID of this counter within its enclosing function. - /// Expressions in the same function can refer to it as an operand. - id: CounterId, - }, - Expression { - /// ID of this coverage-counter expression within its enclosing function. - /// Other expressions in the same function can refer to it as an operand. - id: ExpressionId, - lhs: Operand, - op: Op, - rhs: Operand, - }, - Unreachable, + /// Marks the point in MIR control flow represented by a coverage counter. + /// + /// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this counter can have those references simplified to zero. + CounterIncrement { id: CounterId }, + + /// Marks the point in MIR control-flow represented by a coverage expression. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this expression can have those references simplified to zero. + /// + /// (This is only inserted for expression IDs that are directly used by + /// mappings. Intermediate expressions with no direct mappings are + /// retained/zeroed based on whether they are transitively used.) + ExpressionUsed { id: ExpressionId }, } impl Debug for CoverageKind { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use CoverageKind::*; match self { - Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), - Unreachable => write!(fmt, "Unreachable"), + CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), + ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), } } } @@ -133,3 +137,38 @@ impl Op { matches!(self, Self::Subtract) } } + +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Expression { + pub lhs: CovTerm, + pub op: Op, + pub rhs: CovTerm, +} + +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Mapping { + pub code_region: CodeRegion, + + /// Indicates whether this mapping uses a counter value, expression value, + /// or zero value. + /// + /// FIXME: When we add support for mapping kinds other than `Code` + /// (e.g. branch regions, expansion regions), replace this with a dedicated + /// mapping-kind enum. + pub term: CovTerm, +} + +/// Stores per-function coverage information attached to a `mir::Body`, +/// to be used in conjunction with the individual coverage statements injected +/// into the function's basic blocks. +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct FunctionCoverageInfo { + pub function_source_hash: u64, + pub num_counters: usize, + + pub expressions: IndexVec, + pub mappings: Vec, +} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f979f736b157..3a5ff4dc91fd 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -345,6 +345,14 @@ pub struct Body<'tcx> { pub injection_phase: Option, pub tainted_by_errors: Option, + + /// Per-function coverage information added by the `InstrumentCoverage` + /// pass, to be used in conjunction with the coverage statements injected + /// into this body's blocks. + /// + /// If `-Cinstrument-coverage` is not active, or if an individual function + /// is not eligible for coverage, then this should always be `None`. + pub function_coverage_info: Option>, } impl<'tcx> Body<'tcx> { @@ -392,6 +400,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors, + function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); body @@ -420,6 +429,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors: None, + function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); body diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index c5e3ee575e1a..3b3b61e4e21d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -493,6 +493,27 @@ pub fn write_mir_intro<'tcx>( // Add an empty line before the first block is printed. writeln!(w)?; + if let Some(function_coverage_info) = &body.function_coverage_info { + write_function_coverage_info(function_coverage_info, w)?; + } + + Ok(()) +} + +fn write_function_coverage_info( + function_coverage_info: &coverage::FunctionCoverageInfo, + w: &mut dyn io::Write, +) -> io::Result<()> { + let coverage::FunctionCoverageInfo { expressions, mappings, .. } = function_coverage_info; + + for (id, expression) in expressions.iter_enumerated() { + writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; + } + for coverage::Mapping { term, code_region } in mappings { + writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?; + } + writeln!(w)?; + Ok(()) } @@ -685,13 +706,7 @@ impl Debug for Statement<'_> { AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } - Coverage(box mir::Coverage { ref kind, ref code_regions }) => { - if code_regions.is_empty() { - write!(fmt, "Coverage::{kind:?}") - } else { - write!(fmt, "Coverage::{kind:?} for {code_regions:?}") - } - } + Coverage(box mir::Coverage { ref kind }) => write!(fmt, "Coverage::{kind:?}"), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index c74a9536b633..f407dc4d7ae3 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,5 +1,6 @@ //! Values computed by queries that use MIR. +use crate::mir; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; @@ -445,14 +446,19 @@ pub struct DestructuredConstant<'tcx> { pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], } -/// Coverage information summarized from a MIR if instrumented for source code coverage (see -/// compiler option `-Cinstrument-coverage`). This information is generated by the -/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. +/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass +/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations +/// have had a chance to potentially remove some of them. +/// +/// Used by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] -pub struct CoverageInfo { - /// The total number of coverage region counters added to the MIR `Body`. - pub num_counters: u32, - - /// The total number of coverage region counter expressions added to the MIR `Body`. - pub num_expressions: u32, +pub struct CoverageIdsInfo { + /// Coverage codegen needs to know the highest counter ID that is ever + /// incremented within a function, so that it can set the `num-counters` + /// argument of the `llvm.instrprof.increment` intrinsic. + /// + /// This may be less than the highest counter ID emitted by the + /// InstrumentCoverage MIR pass, if the highest-numbered counter increments + /// were removed by MIR optimizations. + pub max_counter_id: mir::coverage::CounterId, } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index c7d99648f1e2..7a645fb5d62b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -5,7 +5,7 @@ use super::{BasicBlock, Const, Local, UserTypeProjection}; -use crate::mir::coverage::{CodeRegion, CoverageKind}; +use crate::mir::coverage::CoverageKind; use crate::traits::Reveal; use crate::ty::adjustment::PointerCoercion; use crate::ty::GenericArgsRef; @@ -361,11 +361,16 @@ pub enum StatementKind<'tcx> { /// Disallowed after drop elaboration. AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), - /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A - /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage - /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates - /// executable code, to increment a counter variable at runtime, each time the code region is - /// executed. + /// Carries control-flow-sensitive information injected by `-Cinstrument-coverage`, + /// such as where to generate physical coverage-counter-increments during codegen. + /// + /// Coverage statements are used in conjunction with the coverage mappings and other + /// information stored in the function's + /// [`mir::Body::function_coverage_info`](crate::mir::Body::function_coverage_info). + /// (For inlined MIR, take care to look up the *original function's* coverage info.) + /// + /// Interpreters and codegen backends that don't support coverage instrumentation + /// can usually treat this as a no-op. Coverage(Box), /// Denotes a call to an intrinsic that does not require an unwind path and always returns. @@ -514,7 +519,6 @@ pub enum FakeReadCause { #[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, - pub code_regions: Vec, } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 340c5a769dbc..afe94d107521 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -573,24 +573,14 @@ rustc_queries! { separate_provide_extern } - /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` - /// MIR pass (assuming the -Cinstrument-coverage option is enabled). - query coverageinfo(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageInfo { - desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) } + /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass + /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations + /// have had a chance to potentially remove some of them. + query coverage_ids_info(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageIdsInfo { + desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } arena_cache } - /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the - /// function was optimized out before codegen, and before being added to the Coverage Map. - query covered_code_regions(key: DefId) -> &'tcx Vec<&'tcx mir::coverage::CodeRegion> { - desc { - |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", - tcx.def_path_str(key) - } - arena_cache - cache_on_disk_if { key.is_local() } - } - /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own /// `DefId`. This function returns all promoteds in the specified body. The body references /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because @@ -2202,6 +2192,11 @@ rustc_queries! { query generics_require_sized_self(def_id: DefId) -> bool { desc { "check whether the item has a `where Self: Sized` bound" } } + + query cross_crate_inlinable(def_id: DefId) -> bool { + desc { "whether the item should be made inlinable across crates" } + separate_provide_extern + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f7bce93fee55..cad3aac23d87 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -80,54 +80,45 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { - type AdtDef = ty::AdtDef<'tcx>; - type GenericArgsRef = ty::GenericArgsRef<'tcx>; - type GenericArg = ty::GenericArg<'tcx>; type DefId = DefId; + type AdtDef = ty::AdtDef<'tcx>; + type GenericArgs = ty::GenericArgsRef<'tcx>; + type GenericArg = ty::GenericArg<'tcx>; type Binder = Binder<'tcx, T>; - type Ty = Ty<'tcx>; - type Const = ty::Const<'tcx>; - type Region = Region<'tcx>; type Predicate = Predicate<'tcx>; + type PredicateKind = ty::PredicateKind<'tcx>; type TypeAndMut = TypeAndMut<'tcx>; - type Mutability = hir::Mutability; - type Movability = hir::Movability; - type PolyFnSig = PolyFnSig<'tcx>; - type ListBinderExistentialPredicate = &'tcx List>; - type BinderListTy = Binder<'tcx, &'tcx List>>; - type ListTy = &'tcx List>; + type Ty = Ty<'tcx>; + type Tys = &'tcx List>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; - type PlaceholderType = ty::PlaceholderType; + type PlaceholderTy = ty::PlaceholderType; type InferTy = InferTy; type ErrorGuaranteed = ErrorGuaranteed; - type PredicateKind = ty::PredicateKind<'tcx>; + type BoundExistentialPredicates = &'tcx List>; + type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; - + type Const = ty::Const<'tcx>; type InferConst = ty::InferConst<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; + type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ValueConst = ty::ValTree<'tcx>; type ExprConst = ty::Expr<'tcx>; - + type Region = Region<'tcx>; type EarlyBoundRegion = ty::EarlyBoundRegion; type BoundRegion = ty::BoundRegion; type FreeRegion = ty::FreeRegion; - type RegionVid = ty::RegionVid; + type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; fn ty_and_mut_to_parts( TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>, - ) -> (Self::Ty, Self::Mutability) { + ) -> (Self::Ty, ty::Mutability) { (ty, mutbl) } - - fn mutability_is_mut(mutbl: Self::Mutability) -> bool { - mutbl.is_mut() - } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; @@ -1687,7 +1678,6 @@ impl<'tcx> TyCtxt<'tcx> { && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id)) { // If this is an inherent projection. - generics.params.len() + 1 } else { generics.count() @@ -1897,15 +1887,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest)) } - pub fn mk_alias_ty( - self, - def_id: DefId, - args: impl IntoIterator>>, - ) -> ty::AliasTy<'tcx> { - let args = self.check_and_mk_args(def_id, args); - ty::AliasTy { def_id, args, _use_mk_alias_ty_instead: () } - } - pub fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 72390e4bbb03..a861af478594 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -11,7 +11,6 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; -use rustc_span::sym; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; @@ -452,10 +451,6 @@ impl<'tcx> GenericArgs<'tcx> { tcx.mk_args_from_iter(self.iter().take(generics.count())) } - pub fn host_effect_param(&'tcx self) -> Option> { - self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) - } - pub fn print_as_list(&self) -> String { let v = self.iter().map(|arg| arg.to_string()).collect::>(); format!("[{}]", v.join(", ")) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 8e6c1cd4bbb6..44e88d3e2302 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -79,6 +79,10 @@ impl GenericParamDef { } } + pub fn is_host_effect(&self) -> bool { + matches!(self.kind, GenericParamDefKind::Const { is_host_effect: true, .. }) + } + pub fn default_value<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0a425be52ffb..0b308d5dec14 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -245,16 +245,15 @@ impl<'tcx> InstanceDef<'tcx> { // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. return ty.ty_adt_def().map_or(true, |adt_def| { - adt_def.destructor(tcx).map_or_else( - || adt_def.is_enum(), - |dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(), - ) + adt_def + .destructor(tcx) + .map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did)) }); } if let ty::InstanceDef::ThreadLocalShim(..) = *self { return false; } - tcx.codegen_fn_attrs(self.def_id()).requests_inline() + tcx.cross_crate_inlinable(self.def_id()) } pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b7d2e3d9493f..e6cd3dd4d82d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1023,7 +1023,7 @@ impl<'tcx> Term<'tcx> { _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.args)), + ConstKind::Unevaluated(uv) => Some(AliasTy::new(tcx, uv.def, uv.args)), _ => None, }, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index aa8e2e30715e..107b44285ac0 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -10,13 +10,12 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; mod pretty; pub use self::pretty::*; +pub type PrintError = std::fmt::Error; + // FIXME(eddyb) false positive, the lifetime parameters are used with `P: Printer<...>`. #[allow(unused_lifetimes)] pub trait Print<'tcx, P> { - type Output; - type Error; - - fn print(&self, cx: P) -> Result; + fn print(&self, cx: P) -> Result; } /// Interface for outputting user-facing "type-system entities" @@ -29,21 +28,13 @@ pub trait Print<'tcx, P> { // // FIXME(eddyb) find a better name; this is more general than "printing". pub trait Printer<'tcx>: Sized { - type Error; - - type Path; - type Region; - type Type; - type DynExistential; - type Const; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn print_def_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.default_print_def_path(def_id, args) } @@ -53,48 +44,48 @@ pub trait Printer<'tcx>: Sized { args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref) } - fn print_region(self, region: ty::Region<'tcx>) -> Result; + fn print_region(self, region: ty::Region<'tcx>) -> Result; - fn print_type(self, ty: Ty<'tcx>) -> Result; + fn print_type(self, ty: Ty<'tcx>) -> Result; fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result; + ) -> Result; - fn print_const(self, ct: ty::Const<'tcx>) -> Result; + fn print_const(self, ct: ty::Const<'tcx>) -> Result; - fn path_crate(self, cnum: CrateNum) -> Result; + fn path_crate(self, cnum: CrateNum) -> Result; fn path_qualified( self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result; + ) -> Result; fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result; + ) -> Result; fn path_generic_args( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result; + ) -> Result; // Defaults (should not be overridden): @@ -103,7 +94,7 @@ pub trait Printer<'tcx>: Sized { self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let key = self.tcx().def_key(def_id); debug!(?key); @@ -194,7 +185,7 @@ pub trait Printer<'tcx>: Sized { _args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option>, - ) -> Result { + ) -> Result { debug!( "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref @@ -295,34 +286,25 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { - type Output = P::Region; - type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_region(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { - type Output = P::Type; - type Error = P::Error; - - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_type(*self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { - type Output = P::DynExistential; - type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) } } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { - type Output = P::Const; - type Error = P::Error; - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.print_const(*self) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e321f0a7b7f2..d8010c714970 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -205,29 +205,19 @@ impl<'tcx> RegionHighlightMode<'tcx> { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter<'tcx>: - Printer< - 'tcx, - Error = fmt::Error, - Path = Self, - Region = Self, - Type = Self, - DynExistential = Self, - Const = Self, - > + fmt::Write -{ +pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Like `print_def_path` but for value paths. fn print_value_path( self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { self.print_def_path(def_id, args) } - fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { value.as_ref().skip_binder().print(self) } @@ -236,17 +226,17 @@ pub trait PrettyPrinter<'tcx>: self, value: &ty::Binder<'tcx, T>, f: F, - ) -> Result + ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { f(value.as_ref().skip_binder(), self) } /// Prints comma-separated elements. - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -261,10 +251,10 @@ pub trait PrettyPrinter<'tcx>: /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument fn typed_value( mut self, - f: impl FnOnce(Self) -> Result, - t: impl FnOnce(Self) -> Result, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -276,8 +266,8 @@ pub trait PrettyPrinter<'tcx>: /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, - f: impl FnOnce(Self) -> Result, - ) -> Result; + f: impl FnOnce(Self) -> Result, + ) -> Result; /// Returns `true` if the region should be printed in /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`. @@ -291,7 +281,7 @@ pub trait PrettyPrinter<'tcx>: /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> { + fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), PrintError> { if NO_VISIBLE_PATH.with(|flag| flag.get()) { return Ok((self, false)); } @@ -305,10 +295,7 @@ pub trait PrettyPrinter<'tcx>: // For enum variants, if they have an unique name, then we only print the name, otherwise we // print the enum name and the variant name. Otherwise, we do not print anything and let the // caller use the `print_def_path` fallback. - fn force_print_trimmed_def_path( - mut self, - def_id: DefId, - ) -> Result<(Self::Path, bool), Self::Error> { + fn force_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> { let key = self.tcx().def_key(def_id); let visible_parent_map = self.tcx().visible_parent_map(()); let kind = self.tcx().def_kind(def_id); @@ -378,10 +365,7 @@ pub trait PrettyPrinter<'tcx>: } /// Try to see if this path can be trimmed to a unique symbol name. - fn try_print_trimmed_def_path( - mut self, - def_id: DefId, - ) -> Result<(Self::Path, bool), Self::Error> { + fn try_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> { if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?; if trimmed { @@ -423,7 +407,7 @@ pub trait PrettyPrinter<'tcx>: mut self, def_id: DefId, callers: &mut Vec, - ) -> Result<(Self, bool), Self::Error> { + ) -> Result<(Self, bool), PrintError> { define_scoped_cx!(self); debug!("try_print_visible_def_path: def_id={:?}", def_id); @@ -595,7 +579,7 @@ pub trait PrettyPrinter<'tcx>: self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -629,10 +613,10 @@ pub trait PrettyPrinter<'tcx>: fn pretty_path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = print_prefix(self)?; self.generic_delimiters(|mut cx| { @@ -648,7 +632,7 @@ pub trait PrettyPrinter<'tcx>: }) } - fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { + fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { define_scoped_cx!(self); match *ty.kind() { @@ -919,7 +903,7 @@ pub trait PrettyPrinter<'tcx>: mut self, def_id: DefId, args: &'tcx ty::List>, - ) -> Result { + ) -> Result { let tcx = self.tcx(); // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, @@ -1189,7 +1173,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_inherent_projection( self, alias_ty: &ty::AliasTy<'tcx>, - ) -> Result { + ) -> Result { let def_key = self.tcx().def_key(alias_ty.def_id); self.path_generic_args( |cx| { @@ -1213,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -1306,7 +1290,7 @@ pub trait PrettyPrinter<'tcx>: inputs: &[Ty<'tcx>], c_variadic: bool, output: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); p!("(", comma_sep(inputs.iter().copied())); @@ -1328,7 +1312,7 @@ pub trait PrettyPrinter<'tcx>: mut self, ct: ty::Const<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1404,11 +1388,7 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - fn pretty_print_const_scalar( - self, - scalar: Scalar, - ty: Ty<'tcx>, - ) -> Result { + fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result { match scalar { Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty), Scalar::Int(int) => { @@ -1421,7 +1401,7 @@ pub trait PrettyPrinter<'tcx>: mut self, ptr: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); let (alloc_id, offset) = ptr.into_parts(); @@ -1483,7 +1463,7 @@ pub trait PrettyPrinter<'tcx>: int: ScalarInt, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); match ty.kind() { @@ -1545,7 +1525,7 @@ pub trait PrettyPrinter<'tcx>: self, _: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { self.typed_value( |mut this| { this.write_str("&_")?; @@ -1556,7 +1536,7 @@ pub trait PrettyPrinter<'tcx>: ) } - fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { + fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { write!(self, "b\"{}\"", byte_str.escape_ascii())?; Ok(self) } @@ -1566,7 +1546,7 @@ pub trait PrettyPrinter<'tcx>: valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>, print_ty: bool, - ) -> Result { + ) -> Result { define_scoped_cx!(self); if self.should_print_verbose() { @@ -1689,7 +1669,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_closure_as_impl( mut self, closure: ty::ClosureArgs<'tcx>, - ) -> Result { + ) -> Result { let sig = closure.sig(); let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); @@ -1862,14 +1842,6 @@ impl fmt::Write for FmtPrinter<'_, '_> { } impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { - type Error = fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -1878,7 +1850,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { define_scoped_cx!(self); if args.is_empty() { @@ -1933,11 +1905,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { self.default_print_def_path(def_id, args) } - fn print_region(self, region: ty::Region<'tcx>) -> Result { + fn print_region(self, region: ty::Region<'tcx>) -> Result { self.pretty_print_region(region) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { if self.type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) @@ -1951,15 +1923,15 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_dyn_existential( self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { self.pretty_print_dyn_existential(predicates) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, false) } - fn path_crate(mut self, cnum: CrateNum) -> Result { + fn path_crate(mut self, cnum: CrateNum) -> Result { self.empty_path = true; if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { @@ -1980,7 +1952,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_qualified(self_ty, trait_ref)?; self.empty_path = false; Ok(self) @@ -1988,11 +1960,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append_impl( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self = self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -2011,9 +1983,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -2042,9 +2014,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let tcx = self.tcx; @@ -2101,7 +2073,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { let was_in_value = std::mem::replace(&mut self.in_value, true); self = self.print_def_path(def_id, args)?; self.in_value = was_in_value; @@ -2109,30 +2081,30 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { Ok(self) } - fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { self.pretty_in_binder(value) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, - ) -> Result + ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { self.pretty_wrap_binder(value, f) } fn typed_value( mut self, - f: impl FnOnce(Self) -> Result, - t: impl FnOnce(Self) -> Result, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, conversion: &str, - ) -> Result { + ) -> Result { self.write_str("{")?; self = f(self)?; self.write_str(conversion)?; @@ -2145,8 +2117,8 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; let was_in_value = std::mem::replace(&mut self.in_value, false); @@ -2206,7 +2178,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self, p: Pointer, ty: Ty<'tcx>, - ) -> Result { + ) -> Result { let print = |mut this: Self| { define_scoped_cx!(this); if this.print_alloc_ids { @@ -2371,7 +2343,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { value: &ty::Binder<'tcx, T>, ) -> Result<(Self, T, BTreeMap>), fmt::Error> where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { fn name_by_region_index( index: usize, @@ -2541,7 +2513,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2557,7 +2529,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { f: C, ) -> Result where - T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable>, + T: Print<'tcx, Self> + TypeFoldable>, { let old_region_index = self.region_index; let (new, new_value, _) = self.name_all_regions(value)?; @@ -2622,24 +2594,19 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where - T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable>, + T: Print<'tcx, P> + TypeFoldable>, { - type Output = P; - type Error = P::Error; - - fn print(&self, cx: P) -> Result { + fn print(&self, cx: P) -> Result { cx.in_binder(self) } } impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate where - T: Print<'tcx, P, Output = P, Error = P::Error>, - U: Print<'tcx, P, Output = P, Error = P::Error>, + T: Print<'tcx, P>, + U: Print<'tcx, P>, { - type Output = P; - type Error = P::Error; - fn print(&self, mut cx: P) -> Result { + fn print(&self, mut cx: P) -> Result { define_scoped_cx!(cx); p!(print(self.0), ": ", print(self.1)); Ok(cx) @@ -2666,9 +2633,7 @@ macro_rules! forward_display_to_print { macro_rules! define_print_and_forward_display { (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty { - type Output = P; - type Error = fmt::Error; - fn print(&$self, $cx: P) -> Result { + fn print(&$self, $cx: P) -> Result { #[allow(unused_mut)] let mut $cx = $cx; define_scoped_cx!($cx); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 96268006353c..fdfdd6cc8d6d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -288,7 +288,7 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { } def => bug!("unknown alias DefKind: {def:?}"), }; - Ok(relation.tcx().mk_alias_ty(a.def_id, args)) + Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args)) } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 30318e585cb9..fc207a2c350d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1213,11 +1213,20 @@ pub struct AliasTy<'tcx> { pub def_id: DefId, /// This field exists to prevent the creation of `AliasTy` without using - /// [TyCtxt::mk_alias_ty]. - pub(super) _use_mk_alias_ty_instead: (), + /// [AliasTy::new]. + _use_alias_ty_new_instead: (), } impl<'tcx> AliasTy<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: impl IntoIterator>>, + ) -> ty::AliasTy<'tcx> { + let args = tcx.check_and_mk_args(def_id, args); + ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () } + } + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy @@ -1245,7 +1254,7 @@ impl<'tcx> AliasTy<'tcx> { } pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) + AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) } } @@ -1667,8 +1676,11 @@ impl<'tcx> ExistentialProjection<'tcx> { debug_assert!(!self_ty.has_escaping_bound_vars()); ty::ProjectionPredicate { - projection_ty: tcx - .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args)), + projection_ty: AliasTy::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args), + ), term: self.term, } } @@ -1971,7 +1983,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, args)) + Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args)) } /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` @@ -2135,7 +2147,7 @@ impl<'tcx> Ty<'tcx> { item_def_id: DefId, args: impl IntoIterator>>, ) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, args)) + Ty::new_alias(tcx, ty::Projection, AliasTy::new(tcx, item_def_id, args)) } #[inline] diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index e5c2cc6c7bbc..a81f70e3346a 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -60,6 +60,7 @@ pub(super) fn build_custom_mir<'tcx>( tainted_by_errors: None, injection_phase: None, pass_count: 0, + function_coverage_info: None, }; body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 4500bb7ff0f0..74243f1f8f27 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -113,6 +113,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { } // We may have invalidated some `cleanup` blocks so clean those up now. - super::simplify::remove_dead_blocks(tcx, body); + super::simplify::remove_dead_blocks(body); } } diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 77e3dee1fefa..a83ccf8fc3c2 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -19,7 +19,7 @@ const NESTED_INDENT: &str = " "; #[derive(Clone)] pub(super) enum BcbCounter { Counter { id: CounterId }, - Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand }, + Expression { id: ExpressionId }, } impl BcbCounter { @@ -27,10 +27,10 @@ impl BcbCounter { matches!(self, Self::Expression { .. }) } - pub(super) fn as_operand(&self) -> Operand { + pub(super) fn as_term(&self) -> CovTerm { match *self { - BcbCounter::Counter { id, .. } => Operand::Counter(id), - BcbCounter::Expression { id, .. } => Operand::Expression(id), + BcbCounter::Counter { id, .. } => CovTerm::Counter(id), + BcbCounter::Expression { id, .. } => CovTerm::Expression(id), } } } @@ -39,17 +39,7 @@ impl Debug for BcbCounter { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Self::Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), + Self::Expression { id } => write!(fmt, "Expression({:?})", id.index()), } } } @@ -58,7 +48,6 @@ impl Debug for BcbCounter { /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { next_counter_id: CounterId, - next_expression_id: ExpressionId, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec>, @@ -69,10 +58,9 @@ pub(super) struct CoverageCounters { /// Only used by debug assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). bcb_has_incoming_edge_counters: BitSet, - /// Expression nodes that are not directly associated with any particular - /// BCB/edge, but are needed as operands to more complex expressions. - /// These are always [`BcbCounter::Expression`]. - pub(super) intermediate_expressions: Vec, + /// Table of expression data, associating each expression ID with its + /// corresponding operator (+ or -) and its LHS/RHS operands. + expressions: IndexVec, } impl CoverageCounters { @@ -81,12 +69,10 @@ impl CoverageCounters { Self { next_counter_id: CounterId::START, - next_expression_id: ExpressionId::START, - bcb_counters: IndexVec::from_elem_n(None, num_bcbs), bcb_edge_counters: FxHashMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), - intermediate_expressions: Vec::new(), + expressions: IndexVec::new(), } } @@ -106,9 +92,9 @@ impl CoverageCounters { BcbCounter::Counter { id } } - fn make_expression(&mut self, lhs: Operand, op: Op, rhs: Operand) -> BcbCounter { - let id = self.next_expression(); - BcbCounter::Expression { id, lhs, op, rhs } + fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm) -> BcbCounter { + let id = self.expressions.push(Expression { lhs, op, rhs }); + BcbCounter::Expression { id } } /// Counter IDs start from one and go up. @@ -118,19 +104,20 @@ impl CoverageCounters { next } - /// Expression IDs start from 0 and go up. - /// (Counter IDs and Expression IDs are distinguished by the `Operand` enum.) - fn next_expression(&mut self) -> ExpressionId { - let next = self.next_expression_id; - self.next_expression_id = self.next_expression_id + 1; - next + pub(super) fn num_counters(&self) -> usize { + self.next_counter_id.as_usize() + } + + #[cfg(test)] + pub(super) fn num_expressions(&self) -> usize { + self.expressions.len() } fn set_bcb_counter( &mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter, - ) -> Result { + ) -> Result { debug_assert!( // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this @@ -138,14 +125,14 @@ impl CoverageCounters { counter_kind.is_expression() || !self.bcb_has_incoming_edge_counters.contains(bcb), "attempt to add a `Counter` to a BCB target with existing incoming edge counters" ); - let operand = counter_kind.as_operand(); + let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) { Error::from_string(format!( "attempt to set a BasicCoverageBlock coverage counter more than once; \ {bcb:?} already had counter {replaced:?}", )) } else { - Ok(operand) + Ok(term) } } @@ -154,7 +141,7 @@ impl CoverageCounters { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, counter_kind: BcbCounter, - ) -> Result { + ) -> Result { if level_enabled!(tracing::Level::DEBUG) { // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this @@ -167,14 +154,14 @@ impl CoverageCounters { } } self.bcb_has_incoming_edge_counters.insert(to_bcb); - let operand = counter_kind.as_operand(); + let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_edge_counters.insert((from_bcb, to_bcb), counter_kind) { Error::from_string(format!( "attempt to set an edge counter more than once; from_bcb: \ {from_bcb:?} already had counter {replaced:?}", )) } else { - Ok(operand) + Ok(term) } } @@ -199,6 +186,10 @@ impl CoverageCounters { ) -> impl Iterator + '_ { self.bcb_edge_counters.drain() } + + pub(super) fn take_expressions(&mut self) -> IndexVec { + std::mem::take(&mut self.expressions) + } } /// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be @@ -276,7 +267,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, branching_bcb: BasicCoverageBlock, - branching_counter_operand: Operand, + branching_counter_operand: CovTerm, ) -> Result<(), Error> { let branches = self.bcb_branches(branching_bcb); debug!( @@ -324,8 +315,7 @@ impl<'a> MakeBcbCounters<'a> { sumup_counter_operand, ); debug!(" [new intermediate expression: {:?}]", intermediate_expression); - let intermediate_expression_operand = intermediate_expression.as_operand(); - self.coverage_counters.intermediate_expressions.push(intermediate_expression); + let intermediate_expression_operand = intermediate_expression.as_term(); some_sumup_counter_operand.replace(intermediate_expression_operand); } } @@ -356,7 +346,7 @@ impl<'a> MakeBcbCounters<'a> { Ok(()) } - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { + fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { self.recursive_get_or_make_counter_operand(bcb, 1) } @@ -364,7 +354,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, bcb: BasicCoverageBlock, debug_indent_level: usize, - ) -> Result { + ) -> Result { // If the BCB already has a counter, return it. if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] { debug!( @@ -373,7 +363,7 @@ impl<'a> MakeBcbCounters<'a> { bcb, counter_kind, ); - return Ok(counter_kind.as_operand()); + return Ok(counter_kind.as_term()); } // A BCB with only one incoming edge gets a simple `Counter` (via `make_counter()`). @@ -437,8 +427,7 @@ impl<'a> MakeBcbCounters<'a> { NESTED_INDENT.repeat(debug_indent_level), intermediate_expression ); - let intermediate_expression_operand = intermediate_expression.as_operand(); - self.coverage_counters.intermediate_expressions.push(intermediate_expression); + let intermediate_expression_operand = intermediate_expression.as_term(); some_sumup_edge_counter_operand.replace(intermediate_expression_operand); } } @@ -460,7 +449,7 @@ impl<'a> MakeBcbCounters<'a> { &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, - ) -> Result { + ) -> Result { self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb, 1) } @@ -469,7 +458,7 @@ impl<'a> MakeBcbCounters<'a> { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, debug_indent_level: usize, - ) -> Result { + ) -> Result { // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. let successors = self.bcb_successors(from_bcb).iter(); @@ -488,7 +477,7 @@ impl<'a> MakeBcbCounters<'a> { to_bcb, counter_kind ); - return Ok(counter_kind.as_operand()); + return Ok(counter_kind.as_term()); } // Make a new counter to count this edge. diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 63126f4486b6..6fdaff6b4c02 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -104,6 +104,7 @@ struct Instrumentor<'a, 'tcx> { function_source_hash: u64, basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, + mappings: Vec, } impl<'a, 'tcx> Instrumentor<'a, 'tcx> { @@ -144,6 +145,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { function_source_hash, basic_coverage_blocks, coverage_counters, + mappings: Vec::new(), } } @@ -165,9 +167,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` // and all `Expression` dependencies (operands) are also generated, for any other // `BasicCoverageBlock`s not already associated with a coverage span. - // - // Intermediate expressions (used to compute other `Expression` values), which have no - // direct association with any `BasicCoverageBlock`, are accumulated inside `coverage_counters`. let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb); let result = self .coverage_counters @@ -193,24 +192,18 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { // are in fact counted, even though they don't directly contribute to counting // their own independent code region's coverage. self.inject_indirect_counters(); - - // Intermediate expressions will be injected as the final step, after generating - // debug output, if any. - //////////////////////////////////////////////////// }; if let Err(e) = result { bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message) }; - //////////////////////////////////////////////////// - // Finally, inject the intermediate expressions collected along the way. - for intermediate_expression in &self.coverage_counters.intermediate_expressions { - inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(intermediate_expression), - ); - } + self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { + function_source_hash: self.function_source_hash, + num_counters: self.coverage_counters.num_counters(), + expressions: self.coverage_counters.take_expressions(), + mappings: std::mem::take(&mut self.mappings), + })); } /// Injects a single [`StatementKind::Coverage`] for each BCB that has one @@ -229,18 +222,16 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { bug!("Every BasicCoverageBlock should have a Counter or Expression"); }); - // Convert the coverage spans into a vector of code regions to be - // associated with this BCB's coverage statement. - let code_regions = spans - .iter() - .map(|&span| make_code_region(source_map, file_name, span, body_span)) - .collect::>(); + let term = counter_kind.as_term(); + self.mappings.extend(spans.iter().map(|&span| { + let code_region = make_code_region(source_map, file_name, span, body_span); + Mapping { code_region, term } + })); inject_statement( self.mir_body, self.make_mir_coverage_kind(&counter_kind), self.bcb_leader_bb(bcb), - code_regions, ); } } @@ -298,13 +289,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.mir_body, self.make_mir_coverage_kind(&counter_kind), inject_to_bb, - Vec::new(), ); } - BcbCounter::Expression { .. } => inject_intermediate_expression( - self.mir_body, - self.make_mir_coverage_kind(&counter_kind), - ), + // Experessions with no associated spans don't need to inject a statement. + BcbCounter::Expression { .. } => {} } } } @@ -326,12 +314,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind { match *counter_kind { - BcbCounter::Counter { id } => { - CoverageKind::Counter { function_source_hash: self.function_source_hash, id } - } - BcbCounter::Expression { id, lhs, op, rhs } => { - CoverageKind::Expression { id, lhs, op, rhs } - } + BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, + BcbCounter::Expression { id } => CoverageKind::ExpressionUsed { id }, } } } @@ -359,39 +343,17 @@ fn inject_edge_counter_basic_block( new_bb } -fn inject_statement( - mir_body: &mut mir::Body<'_>, - counter_kind: CoverageKind, - bb: BasicBlock, - code_regions: Vec, -) { - debug!(" injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}"); +fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb: BasicBlock) { + debug!(" injecting statement {counter_kind:?} for {bb:?}"); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; let statement = Statement { source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })), + kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind })), }; data.statements.insert(0, statement); } -// Non-code expressions are injected into the coverage map, without generating executable code. -fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) { - debug_assert!(matches!(expression, CoverageKind::Expression { .. })); - debug!(" injecting non-code expression {:?}", expression); - let inject_in_bb = mir::START_BLOCK; - let data = &mut mir_body[inject_in_bb]; - let source_info = data.terminator().source_info; - let statement = Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: expression, - code_regions: Vec::new(), - })), - }; - data.statements.push(statement); -} - /// Convert the Span into its file name, start line and column, and end line and column fn make_code_region( source_map: &SourceMap, diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 2c0164e765c7..809407f897db 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -2,100 +2,31 @@ use super::*; use rustc_data_structures::captures::Captures; use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; +use rustc_middle::mir::{Body, Coverage, CoverageIdsInfo}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::def_id::DefId; /// A `query` provider for retrieving coverage information injected into MIR. pub(crate) fn provide(providers: &mut Providers) { - providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id); - providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); + providers.coverage_ids_info = |tcx, def_id| coverage_ids_info(tcx, def_id); } -/// Coverage codegen needs to know the total number of counter IDs and expression IDs that have -/// been used by a function's coverage mappings. These totals are used to create vectors to hold -/// the relevant counter and expression data, and the maximum counter ID (+ 1) is also needed by -/// the `llvm.instrprof.increment` intrinsic. -/// -/// MIR optimization may split and duplicate some BasicBlock sequences, or optimize out some code -/// including injected counters. (It is OK if some counters are optimized out, but those counters -/// are still included in the total `num_counters` or `num_expressions`.) Simply counting the -/// calls may not work; but computing the number of counters or expressions by adding `1` to the -/// highest ID (for a given instrumented function) is valid. -/// -/// It's possible for a coverage expression to remain in MIR while one or both of its operands -/// have been optimized away. To avoid problems in codegen, we include those operands' IDs when -/// determining the maximum counter/expression ID, even if the underlying counter/expression is -/// no longer present. -struct CoverageVisitor { - max_counter_id: CounterId, - max_expression_id: ExpressionId, -} - -impl CoverageVisitor { - /// Updates `max_counter_id` to the maximum encountered counter ID. - #[inline(always)] - fn update_max_counter_id(&mut self, counter_id: CounterId) { - self.max_counter_id = self.max_counter_id.max(counter_id); - } - - /// Updates `max_expression_id` to the maximum encountered expression ID. - #[inline(always)] - fn update_max_expression_id(&mut self, expression_id: ExpressionId) { - self.max_expression_id = self.max_expression_id.max(expression_id); - } - - fn update_from_expression_operand(&mut self, operand: Operand) { - match operand { - Operand::Counter(id) => self.update_max_counter_id(id), - Operand::Expression(id) => self.update_max_expression_id(id), - Operand::Zero => {} - } - } - - fn visit_body(&mut self, body: &Body<'_>) { - for coverage in all_coverage_in_mir_body(body) { - self.visit_coverage(coverage); - } - } - - fn visit_coverage(&mut self, coverage: &Coverage) { - match coverage.kind { - CoverageKind::Counter { id, .. } => self.update_max_counter_id(id), - CoverageKind::Expression { id, lhs, rhs, .. } => { - self.update_max_expression_id(id); - self.update_from_expression_operand(lhs); - self.update_from_expression_operand(rhs); - } - CoverageKind::Unreachable => {} - } - } -} - -fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> CoverageInfo { +/// Query implementation for `coverage_ids_info`. +fn coverage_ids_info<'tcx>( + tcx: TyCtxt<'tcx>, + instance_def: ty::InstanceDef<'tcx>, +) -> CoverageIdsInfo { let mir_body = tcx.instance_mir(instance_def); - let mut coverage_visitor = CoverageVisitor { - max_counter_id: CounterId::START, - max_expression_id: ExpressionId::START, - }; + let max_counter_id = all_coverage_in_mir_body(mir_body) + .filter_map(|coverage| match coverage.kind { + CoverageKind::CounterIncrement { id } => Some(id), + _ => None, + }) + .max() + .unwrap_or(CounterId::START); - coverage_visitor.visit_body(mir_body); - - // Add 1 to the highest IDs to get the total number of IDs. - CoverageInfo { - num_counters: (coverage_visitor.max_counter_id + 1).as_u32(), - num_expressions: (coverage_visitor.max_expression_id + 1).as_u32(), - } -} - -fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { - let body = mir_body(tcx, def_id); - all_coverage_in_mir_body(body) - // Coverage statements have a list of code regions (possibly empty). - .flat_map(|coverage| coverage.code_regions.as_slice()) - .collect() + CoverageIdsInfo { max_counter_id } } fn all_coverage_in_mir_body<'a, 'tcx>( @@ -115,11 +46,3 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() } - -/// This function ensures we obtain the correct MIR for the given item irrespective of -/// whether that means const mir or runtime mir. For `const fn` this opts for runtime -/// mir. -fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> { - let def = ty::InstanceDef::Item(def_id); - tcx.instance_mir(def) -} diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 1d1be8f24927..f1a0f762041c 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -404,7 +404,7 @@ impl<'a> CoverageSpansGenerator<'a> { let Some(visible_macro) = curr.visible_macro(self.body_span) else { return }; if let Some(prev) = &self.some_prev - && prev.expn_span.ctxt() == curr.expn_span.ctxt() + && prev.expn_span.eq_ctxt(curr.expn_span) { return; } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 487d22823644..795cbce963d1 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -656,7 +656,7 @@ fn test_make_bcb_counters() { coverage_counters .make_bcb_counters(&mut basic_coverage_blocks, bcb_has_coverage_spans) .expect("should be Ok"); - assert_eq!(coverage_counters.intermediate_expressions.len(), 0); + assert_eq!(coverage_counters.num_expressions(), 0); let_bcb!(1); assert_eq!( diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs new file mode 100644 index 000000000000..24d081f2ac9a --- /dev/null +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -0,0 +1,119 @@ +use rustc_attr::InlineAttr; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::*; +use rustc_middle::query::Providers; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::OptLevel; + +pub fn provide(providers: &mut Providers) { + providers.cross_crate_inlinable = cross_crate_inlinable; +} + +fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); + // If this has an extern indicator, then this function is globally shared and thus will not + // generate cgu-internal copies which would make it cross-crate inlinable. + if codegen_fn_attrs.contains_extern_indicator() { + return false; + } + + // Obey source annotations first; this is important because it means we can use + // #[inline(never)] to force code generation. + match codegen_fn_attrs.inline { + InlineAttr::Never => return false, + InlineAttr::Hint | InlineAttr::Always => return true, + _ => {} + } + + // This just reproduces the logic from Instance::requires_inline. + match tcx.def_kind(def_id) { + DefKind::Ctor(..) | DefKind::Closure => return true, + DefKind::Fn | DefKind::AssocFn => {} + _ => return false, + } + + // Don't do any inference when incremental compilation is enabled; the additional inlining that + // inference permits also creates more work for small edits. + if tcx.sess.opts.incremental.is_some() { + return false; + } + + // Don't do any inference unless optimizations are enabled. + if matches!(tcx.sess.opts.optimize, OptLevel::No) { + return false; + } + + if !tcx.is_mir_available(def_id) { + return false; + } + + let mir = tcx.optimized_mir(def_id); + let mut checker = + CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 }; + checker.visit_body(mir); + checker.calls == 0 + && checker.resumes == 0 + && checker.landing_pads == 0 + && checker.statements + <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100) +} + +struct CostChecker<'b, 'tcx> { + tcx: TyCtxt<'tcx>, + callee_body: &'b Body<'tcx>, + calls: usize, + statements: usize, + landing_pads: usize, + resumes: usize, +} + +impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { + fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { + // Don't count StorageLive/StorageDead in the inlining cost. + match statement.kind { + StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Deinit(_) + | StatementKind::Nop => {} + _ => self.statements += 1, + } + } + + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _: Location) { + let tcx = self.tcx; + match terminator.kind { + TerminatorKind::Drop { ref place, unwind, .. } => { + let ty = place.ty(self.callee_body, tcx).ty; + if !ty.is_trivially_pure_clone_copy() { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + } + TerminatorKind::Call { unwind, .. } => { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::Assert { unwind, .. } => { + self.calls += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::UnwindResume => self.resumes += 1, + TerminatorKind::InlineAsm { unwind, .. } => { + self.statements += 1; + if let UnwindAction::Cleanup(_) = unwind { + self.landing_pads += 1; + } + } + TerminatorKind::Return => {} + _ => self.statements += 1, + } + } +} diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index d9a132e5cf17..99b070c018e3 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -244,7 +244,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { if round_count != 0 { // Merging can introduce overlap between moved arguments and/or call destination in an // unreachable code, which validator considers to be ill-formed. - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); } trace!(round_count); diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index c16f07a453c3..a6693519e54b 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1088,7 +1088,7 @@ fn create_generator_drop_shim<'tcx>( // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function - simplify::remove_dead_blocks(tcx, &mut body); + simplify::remove_dead_blocks(&mut body); // Update the body's def to become the drop glue. // This needs to be updated before the AbortUnwindingCalls pass. @@ -1276,7 +1276,7 @@ fn create_generator_resume_function<'tcx>( // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function - simplify::remove_dead_blocks(tcx, body); + simplify::remove_dead_blocks(body); pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 06ae070c9083..8f578b696944 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -63,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for Inline { if inline(tcx, body) { debug!("running simplify cfg on {:?}", body.source); CfgSimplifier::new(body).simplify(); - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); deref_finder(tcx, body); } } @@ -169,8 +169,11 @@ impl<'tcx> Inliner<'tcx> { caller_body: &mut Body<'tcx>, callsite: &CallSite<'tcx>, ) -> Result, &'static str> { + self.check_mir_is_available(caller_body, &callsite.callee)?; + let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id()); - self.check_codegen_attributes(callsite, callee_attrs)?; + let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id()); + self.check_codegen_attributes(callsite, callee_attrs, cross_crate_inlinable)?; let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; @@ -183,9 +186,8 @@ impl<'tcx> Inliner<'tcx> { } } - self.check_mir_is_available(caller_body, &callsite.callee)?; let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?; - self.check_mir_body(callsite, callee_body, callee_attrs)?; + self.check_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?; if !self.tcx.consider_optimizing(|| { format!("Inline {:?} into {:?}", callsite.callee, caller_body.source) @@ -401,6 +403,7 @@ impl<'tcx> Inliner<'tcx> { &self, callsite: &CallSite<'tcx>, callee_attrs: &CodegenFnAttrs, + cross_crate_inlinable: bool, ) -> Result<(), &'static str> { if let InlineAttr::Never = callee_attrs.inline { return Err("never inline hint"); @@ -414,7 +417,7 @@ impl<'tcx> Inliner<'tcx> { .non_erasable_generics(self.tcx, callsite.callee.def_id()) .next() .is_some(); - if !is_generic && !callee_attrs.requests_inline() { + if !is_generic && !cross_crate_inlinable { return Err("not exported"); } @@ -456,10 +459,11 @@ impl<'tcx> Inliner<'tcx> { callsite: &CallSite<'tcx>, callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs, + cross_crate_inlinable: bool, ) -> Result<(), &'static str> { let tcx = self.tcx; - let mut threshold = if callee_attrs.requests_inline() { + let mut threshold = if cross_crate_inlinable { self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100) } else { self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 78f76f1e5136..d579420ecb83 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -62,6 +62,7 @@ mod const_prop; mod const_prop_lint; mod copy_prop; mod coverage; +mod cross_crate_inline; mod ctfe_limit; mod dataflow_const_prop; mod dead_store_elimination; @@ -123,6 +124,7 @@ pub fn provide(providers: &mut Providers) { coverage::query::provide(providers); ffi_unwind_calls::provide(providers); shim::provide(providers); + cross_crate_inline::provide(providers); *providers = Providers { mir_keys, mir_const, @@ -381,7 +383,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { // Do not compute the mir call graph without said call graph actually being used. - if inline::Inline.is_enabled(&tcx.sess) { + if pm::should_run_pass(tcx, &inline::Inline) { tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id())); } } diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index c97d034544a8..c9b42e75cb25 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -38,6 +38,6 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { } } - simplify::remove_dead_blocks(tcx, body) + simplify::remove_dead_blocks(body) } } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 5abb2f3d0412..a8aba29adcd1 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -83,6 +83,25 @@ pub fn run_passes<'tcx>( run_passes_inner(tcx, body, passes, phase_change, true); } +pub fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool +where + P: MirPass<'tcx> + ?Sized, +{ + let name = pass.name(); + + let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; + let overridden = + overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { + trace!( + pass = %name, + "{} as requested by flag", + if *polarity { "Running" } else { "Not running" }, + ); + *polarity + }); + overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) +} + fn run_passes_inner<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, @@ -100,19 +119,9 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map( - |(_name, polarity)| { - trace!( - pass = %name, - "{} as requested by flag", - if *polarity { "Running" } else { "Not running" }, - ); - *polarity - }, - ); - if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + if !should_run_pass(tcx, *pass) { continue; - } + }; let dump_enabled = pass.is_mir_dump_enabled(); diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 73dae0443553..88c89e106fd5 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -28,10 +28,8 @@ //! return. use crate::MirPass; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_index::bit_set::BitSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -68,7 +66,7 @@ impl SimplifyCfg { pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { CfgSimplifier::new(body).simplify(); remove_duplicate_unreachable_blocks(tcx, body); - remove_dead_blocks(tcx, body); + remove_dead_blocks(body); // FIXME: Should probably be moved into some kind of pass manager body.basic_blocks_mut().raw.shrink_to_fit(); @@ -337,7 +335,7 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B } } -pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn remove_dead_blocks(body: &mut Body<'_>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks.len(); if num_blocks == reachable.count() { @@ -345,10 +343,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } let basic_blocks = body.basic_blocks.as_mut(); - let source_scopes = &body.source_scopes; - if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, source_scopes, &reachable); - } let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut orig_index = 0; @@ -370,99 +364,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -/// Some MIR transforms can determine at compile time that a sequences of -/// statements will never be executed, so they can be dropped from the MIR. -/// For example, an `if` or `else` block that is guaranteed to never be executed -/// because its condition can be evaluated at compile time, such as by const -/// evaluation: `if false { ... }`. -/// -/// Those statements are bypassed by redirecting paths in the CFG around the -/// `dead blocks`; but with `-C instrument-coverage`, the dead blocks usually -/// include `Coverage` statements representing the Rust source code regions to -/// be counted at runtime. Without these `Coverage` statements, the regions are -/// lost, and the Rust source code will show no coverage information. -/// -/// What we want to show in a coverage report is the dead code with coverage -/// counts of `0`. To do this, we need to save the code regions, by injecting -/// `Unreachable` coverage statements. These are non-executable statements whose -/// code regions are still recorded in the coverage map, representing regions -/// with `0` executions. -/// -/// If there are no live `Counter` `Coverage` statements remaining, we remove -/// `Coverage` statements along with the dead blocks. Since at least one -/// counter per function is required by LLVM (and necessary, to add the -/// `function_hash` to the counter's call to the LLVM intrinsic -/// `instrprof.increment()`). -/// -/// The `generator::StateTransform` MIR pass and MIR inlining can create -/// atypical conditions, where all live `Counter`s are dropped from the MIR. -/// -/// With MIR inlining we can have coverage counters belonging to different -/// instances in a single body, so the strategy described above is applied to -/// coverage counters from each instance individually. -fn save_unreachable_coverage( - basic_blocks: &mut IndexSlice>, - source_scopes: &IndexSlice>, - reachable: &BitSet, -) { - // Identify instances that still have some live coverage counters left. - let mut live = FxHashSet::default(); - for bb in reachable.iter() { - let basic_block = &basic_blocks[bb]; - for statement in &basic_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - let CoverageKind::Counter { .. } = coverage.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - live.insert(instance); - } - } - - for bb in reachable.iter() { - let block = &mut basic_blocks[bb]; - for statement in &mut block.statements { - let StatementKind::Coverage(_) = &statement.kind else { continue }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if !live.contains(&instance) { - statement.make_nop(); - } - } - } - - if live.is_empty() { - return; - } - - // Retain coverage for instances that still have some live counters left. - let mut retained_coverage = Vec::new(); - for dead_block in basic_blocks.indices() { - if reachable.contains(dead_block) { - continue; - } - let dead_block = &basic_blocks[dead_block]; - for statement in &dead_block.statements { - let StatementKind::Coverage(coverage) = &statement.kind else { continue }; - if coverage.code_regions.is_empty() { - continue; - }; - let instance = statement.source_info.scope.inlined_instance(source_scopes); - if live.contains(&instance) { - retained_coverage.push((statement.source_info, coverage.code_regions.clone())); - } - } - } - - let start_block = &mut basic_blocks[START_BLOCK]; - start_block.statements.extend(retained_coverage.into_iter().map( - |(source_info, code_regions)| Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { - kind: CoverageKind::Unreachable, - code_regions, - })), - }, - )); -} - pub enum SimplifyLocals { BeforeConstProp, Final, diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 0b9311a20efa..ea7aafd866b1 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -65,7 +65,7 @@ impl MirPass<'_> for UnreachablePropagation { } if replaced { - simplify::remove_dead_blocks(tcx, body); + simplify::remove_dead_blocks(body); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8b408d8202eb..dfe75ea5e8e1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1776,6 +1776,7 @@ impl CheckAttrVisitor<'_> { .collect(); let mut int_reprs = 0; + let mut is_explicit_rust = false; let mut is_c = false; let mut is_simd = false; let mut is_transparent = false; @@ -1787,7 +1788,9 @@ impl CheckAttrVisitor<'_> { } match hint.name_or_empty() { - sym::Rust => {} + sym::Rust => { + is_explicit_rust = true; + } sym::C => { is_c = true; match target { @@ -1897,12 +1900,16 @@ impl CheckAttrVisitor<'_> { // Error on repr(transparent, ). if is_transparent && hints.len() > 1 { - let hint_spans: Vec<_> = hint_spans.clone().collect(); + let hint_spans = hint_spans.clone().collect(); self.tcx.sess.emit_err(errors::TransparentIncompatible { hint_spans, target: target.to_string(), }); } + if is_explicit_rust && (int_reprs > 0 || is_c || is_simd) { + let hint_spans = hint_spans.clone().collect(); + self.tcx.sess.emit_err(errors::ReprConflicting { hint_spans }); + } // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8) if (int_reprs > 1) || (is_simd && is_c) @@ -1919,7 +1926,7 @@ impl CheckAttrVisitor<'_> { CONFLICTING_REPR_HINTS, hir_id, hint_spans.collect::>(), - errors::ReprConflicting, + errors::ReprConflictingLint, ); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index a4397ceeb8cc..6f87b56c636d 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -558,9 +558,16 @@ pub struct ReprIdent { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_repr_conflicting, code = "E0566")] +pub struct ReprConflicting { + #[primary_span] + pub hint_spans: Vec, +} + #[derive(LintDiagnostic)] #[diag(passes_repr_conflicting, code = "E0566")] -pub struct ReprConflicting; +pub struct ReprConflictingLint; #[derive(Diagnostic)] #[diag(passes_used_static)] diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 4590ab9e4f57..25e131d7477f 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -231,7 +231,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { AsyncClosure(closure_span) => { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } - UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => { + UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => { let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion }); } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index e93368a84bad..650bb97c4d16 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -18,43 +18,10 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::CrateType; use rustc_target::spec::abi::Abi; -// Returns true if the given item must be inlined because it may be -// monomorphized or it was marked with `#[inline]`. This will only return -// true for functions. -fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { - if attrs.requests_inline() { - return true; - } - - match item.kind { - hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, - hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { - let generics = tcx.generics_of(item.owner_id); - generics.requires_monomorphization(tcx) - } - _ => false, - } -} - -fn method_might_be_inlined( - tcx: TyCtxt<'_>, - impl_item: &hir::ImplItem<'_>, - impl_src: LocalDefId, -) -> bool { - let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id()); - let generics = tcx.generics_of(impl_item.owner_id); - if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { - return true; - } - if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind { - if method_sig.header.is_const() { - return true; - } - } - match tcx.hir().find_by_def_id(impl_src) { - Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs), - Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"), - } +fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + tcx.generics_of(def_id).requires_monomorphization(tcx) + || tcx.cross_crate_inlinable(def_id) + || tcx.is_const_fn(def_id) } // Information needed while computing reachability. @@ -150,9 +117,7 @@ impl<'tcx> ReachableContext<'tcx> { match self.tcx.hir().find_by_def_id(def_id) { Some(Node::Item(item)) => match item.kind { - hir::ItemKind::Fn(..) => { - item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)) - } + hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()), _ => false, }, Some(Node::TraitItem(trait_method)) => match trait_method.kind { @@ -164,9 +129,7 @@ impl<'tcx> ReachableContext<'tcx> { Some(Node::ImplItem(impl_item)) => match impl_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Fn(..) => { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let impl_did = self.tcx.hir().get_parent_item(hir_id); - method_might_be_inlined(self.tcx, impl_item, impl_did.def_id) + item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) } hir::ImplItemKind::Type(_) => false, }, @@ -226,11 +189,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::Item(item) => { match item.kind { hir::ItemKind::Fn(.., body) => { - if item_might_be_inlined( - self.tcx, - &item, - self.tcx.codegen_fn_attrs(item.owner_id), - ) { + if item_might_be_inlined(self.tcx, item.owner_id.into()) { self.visit_nested_body(body); } } @@ -279,8 +238,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body); } hir::ImplItemKind::Fn(_, body) => { - let impl_def_id = self.tcx.local_parent(search_item); - if method_might_be_inlined(self.tcx, impl_item, impl_def_id) { + if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) { self.visit_nested_body(body) } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9561c7ba7603..c090bcaf9d8e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1477,6 +1477,8 @@ options! { "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), + cross_crate_inline_threshold: Option = (None, parse_opt_number, [TRACKED], + "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), debug_macros: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index e3c84f06543e..5ea805e5739b 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -6,9 +6,11 @@ use crate::rustc_internal; use crate::rustc_smir::Tables; use rustc_data_structures::fx; +use rustc_data_structures::fx::FxIndexMap; use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; +use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; @@ -97,7 +99,7 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::Prov(self.create_alloc_id(aid)) } - fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { + pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { self.def_ids.create_or_fetch(did) } @@ -108,6 +110,17 @@ impl<'tcx> Tables<'tcx> { pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span { self.spans.create_or_fetch(span) } + + pub(crate) fn instance_def( + &mut self, + instance: ty::Instance<'tcx>, + ) -> stable_mir::mir::mono::InstanceDef { + self.instances.create_or_fetch(instance) + } + + pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef { + stable_mir::mir::mono::StaticDef(self.create_def_id(did)) + } } pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { @@ -118,10 +131,11 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { stable_mir::run( Tables { tcx, - def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, - alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, - spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() }, + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), types: vec![], + instances: IndexMap::default(), }, f, ); @@ -192,6 +206,12 @@ pub struct IndexMap { index_map: fx::FxIndexMap, } +impl Default for IndexMap { + fn default() -> Self { + Self { index_map: FxIndexMap::default() } + } +} + impl IndexMap { pub fn create_or_fetch(&mut self, key: K) -> V { let len = self.index_map.len(); diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index f26d18ad38f2..94dc15b4767c 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -13,10 +13,12 @@ use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region}; use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; -use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; +use rustc_middle::mir::mono::MonoItem; +use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_target::abi::FieldIdx; -use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; +use stable_mir::mir::mono::InstanceDef; +use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; use stable_mir::ty::{ FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; @@ -119,29 +121,7 @@ impl<'tcx> Context for Tables<'tcx> { fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { let def_id = self[item]; - let mir = self.tcx.instance_mir(ty::InstanceDef::Item(def_id)); - stable_mir::mir::Body { - blocks: mir - .basic_blocks - .iter() - .map(|block| stable_mir::mir::BasicBlock { - terminator: block.terminator().stable(self), - statements: block - .statements - .iter() - .map(|statement| statement.stable(self)) - .collect(), - }) - .collect(), - locals: mir - .local_decls - .iter() - .map(|decl| stable_mir::mir::LocalDecl { - ty: self.intern_ty(decl.ty), - span: decl.source_info.span.stable(self), - }) - .collect(), - } + self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self) } fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { @@ -190,6 +170,34 @@ impl<'tcx> Context for Tables<'tcx> { .collect(), } } + + fn instance_body(&mut self, _def: InstanceDef) -> Body { + todo!("Monomorphize the body") + } + + fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty { + let instance = self.instances[def]; + let ty = instance.ty(self.tcx, ParamEnv::empty()); + self.intern_ty(ty) + } + + fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId { + let def_id = self.instances[def].def_id(); + self.create_def_id(def_id) + } + + fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + let def_id = self[item.0]; + Instance::mono(self.tcx, def_id).stable(self) + } + + fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { + let def_id = self[def_id]; + let generics = self.tcx.generics_of(def_id); + let result = generics.requires_monomorphization(self.tcx); + println!("req {result}: {def_id:?}"); + result + } } #[derive(Clone)] @@ -224,7 +232,8 @@ pub struct Tables<'tcx> { pub def_ids: IndexMap, pub alloc_ids: IndexMap, pub spans: IndexMap, - pub types: Vec>>, + pub types: Vec>>, + pub instances: IndexMap, InstanceDef>, } impl<'tcx> Tables<'tcx> { @@ -254,6 +263,35 @@ pub(crate) trait Stable<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T; } +impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { + type T = stable_mir::mir::Body; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + stable_mir::mir::Body { + blocks: self + .basic_blocks + .iter() + .map(|block| stable_mir::mir::BasicBlock { + terminator: block.terminator().stable(tables), + statements: block + .statements + .iter() + .map(|statement| statement.stable(tables)) + .collect(), + }) + .collect(), + locals: self + .local_decls + .iter() + .map(|decl| stable_mir::mir::LocalDecl { + ty: tables.intern_ty(decl.ty), + span: decl.source_info.span.stable(tables), + }) + .collect(), + } + } +} + impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { @@ -1637,3 +1675,38 @@ impl<'tcx> Stable<'tcx> for DefKind { opaque(self) } } + +impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { + type T = stable_mir::mir::mono::Instance; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let def = tables.instance_def(*self); + let kind = match self.def { + ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item, + ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, + ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual, + ty::InstanceDef::VTableShim(..) + | ty::InstanceDef::ReifyShim(..) + | ty::InstanceDef::FnPtrAddrShim(..) + | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ThreadLocalShim(..) + | ty::InstanceDef::DropGlue(..) + | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim, + }; + stable_mir::mir::mono::Instance { def, kind } + } +} + +impl<'tcx> Stable<'tcx> for MonoItem<'tcx> { + type T = stable_mir::mir::mono::MonoItem; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::mir::mono::MonoItem as StableMonoItem; + match self { + MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)), + MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)), + MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)), + } + } +} diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index bfc9e125362c..f7d17a267d69 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -212,6 +212,7 @@ impl Span { /// This function is used as a fast path when decoding the full `SpanData` is not necessary. /// It's a cut-down version of `data_untracked`. + #[cfg_attr(not(test), rustc_diagnostic_item = "SpanCtxt")] #[inline] pub fn ctxt(self) -> SyntaxContext { if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ea261923c654..be8c65862dc2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -303,6 +303,7 @@ symbols! { SliceIndex, SliceIter, Some, + SpanCtxt, String, StructuralEq, StructuralPartialEq, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 2fc102bda134..5290da9a25b9 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -1,7 +1,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::ty::print::{PrettyPrinter, Print, Printer}; +use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_middle::util::common::record_time; @@ -200,23 +200,15 @@ struct SymbolPrinter<'tcx> { // symbol names should have their own printing machinery. impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { - type Error = fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn print_region(self, _region: ty::Region<'_>) -> Result { + fn print_region(self, _region: ty::Region<'_>) -> Result { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { match *ty.kind() { // Print all nominal types as paths (unlike `pretty_print_type`). ty::FnDef(def_id, args) @@ -250,7 +242,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { let mut first = true; for p in predicates { if !first { @@ -262,7 +254,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn print_const(self, ct: ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { // only print integers match (ct.kind(), ct.ty().kind()) { (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => { @@ -280,7 +272,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(self) } @@ -288,7 +280,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { @@ -304,11 +296,11 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn path_append_impl( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { self.pretty_path_append_impl( |mut cx| { cx = print_prefix(cx)?; @@ -328,9 +320,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_append( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { self = print_prefix(self)?; // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. @@ -351,9 +343,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { self = print_prefix(self)?; let args = @@ -371,9 +363,9 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } - fn comma_sep(mut self, mut elems: impl Iterator) -> Result + fn comma_sep(mut self, mut elems: impl Iterator) -> Result where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + T: Print<'tcx, Self>, { if let Some(first) = elems.next() { self = first.print(self)?; @@ -387,8 +379,8 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn generic_delimiters( mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { + f: impl FnOnce(Self) -> Result, + ) -> Result { write!(self, "<")?; let kept_within_component = mem::replace(&mut self.keep_within_component, true); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 82b1a772e3d7..99c5d0164399 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::print::{Print, Printer}; +use rustc_middle::ty::print::{Print, PrintError, Printer}; use rustc_middle::ty::{ self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, UintTy, @@ -181,11 +181,11 @@ impl<'tcx> SymbolMangler<'tcx> { fn path_append_ns<'a>( mut self: &'a mut Self, - print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, !>, + print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, PrintError>, ns: char, disambiguator: u64, name: &str, - ) -> Result<&'a mut Self, !> { + ) -> Result<&'a mut Self, PrintError> { self.push("N"); self.out.push(ns); self = print_prefix(self)?; @@ -194,7 +194,7 @@ impl<'tcx> SymbolMangler<'tcx> { Ok(self) } - fn print_backref(&mut self, i: usize) -> Result<&mut Self, !> { + fn print_backref(&mut self, i: usize) -> Result<&mut Self, PrintError> { self.push("B"); self.push_integer_62((i - self.start_offset) as u64); Ok(self) @@ -203,8 +203,8 @@ impl<'tcx> SymbolMangler<'tcx> { fn in_binder<'a, T>( mut self: &'a mut Self, value: &ty::Binder<'tcx, T>, - print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, !>, - ) -> Result<&'a mut Self, !> + print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, PrintError>, + ) -> Result<&'a mut Self, PrintError> where T: TypeVisitable>, { @@ -230,14 +230,6 @@ impl<'tcx> SymbolMangler<'tcx> { } impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { - type Error = !; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -246,7 +238,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], - ) -> Result { + ) -> Result { if let Some(&i) = self.paths.get(&(def_id, args)) { return self.print_backref(i); } @@ -268,7 +260,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { args: &'tcx [GenericArg<'tcx>], mut self_ty: Ty<'tcx>, mut impl_trait_ref: Option>, - ) -> Result { + ) -> Result { let key = self.tcx.def_key(impl_def_id); let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; @@ -321,7 +313,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_region(self, region: ty::Region<'_>) -> Result { + fn print_region(self, region: ty::Region<'_>) -> Result { let i = match *region { // Erased lifetimes use the index 0, for a // shorter mangling of `L_`. @@ -343,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_type(mut self, ty: Ty<'tcx>) -> Result { + fn print_type(mut self, ty: Ty<'tcx>) -> Result { // Basic types, never cached (single-character). let basic_type = match ty.kind() { ty::Bool => "b", @@ -498,7 +490,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { // Okay, so this is a bit tricky. Imagine we have a trait object like // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the // output looks really close to the syntax, where the `Bar = &'a ()` bit @@ -559,7 +551,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { + fn print_const(mut self, ct: ty::Const<'tcx>) -> Result { // We only mangle a typed value if the const can be evaluated. let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all()); match ct.kind() { @@ -731,7 +723,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { Ok(self) } - fn path_crate(self, cnum: CrateNum) -> Result { + fn path_crate(self, cnum: CrateNum) -> Result { self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.as_u64()); @@ -744,7 +736,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { mut self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { assert!(trait_ref.is_some()); let trait_ref = trait_ref.unwrap(); @@ -755,20 +747,20 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_append_impl( self, - _: impl FnOnce(Self) -> Result, + _: impl FnOnce(Self) -> Result, _: &DisambiguatedDefPathData, _: Ty<'tcx>, _: Option>, - ) -> Result { + ) -> Result { // Inlined into `print_impl_path` unreachable!() } fn path_append( self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { + ) -> Result { let ns = match disambiguated_data.data { // Extern block segments can be skipped, names from extern blocks // are effectively living in their parent modules. @@ -806,9 +798,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn path_generic_args( mut self, - print_prefix: impl FnOnce(Self) -> Result, + print_prefix: impl FnOnce(Self) -> Result, args: &[GenericArg<'tcx>], - ) -> Result { + ) -> Result { // Don't print any regions if they're all erased. let print_regions = args.iter().any(|arg| match arg.unpack() { GenericArgKind::Lifetime(r) => !r.is_erased(), diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 872f0c879160..b0a348985708 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -129,7 +129,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { self.at.cause.clone(), self.at.param_env, ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(uv.def, uv.args), + projection_ty: AliasTy::new(tcx, uv.def, uv.args), term: new_infer_ct.into(), }, ); diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 2c000293f268..73c8d0c85dda 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -352,8 +352,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let pred = tupled_inputs_and_output .map_bound(|(inputs, output)| ty::ProjectionPredicate { - projection_ty: tcx - .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]), + projection_ty: ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [goal.predicate.self_ty(), inputs], + ), term: output.into(), }) .to_predicate(tcx); @@ -472,7 +475,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx, goal, ty::ProjectionPredicate { - projection_ty: ecx.tcx().mk_alias_ty(goal.predicate.def_id(), [self_ty]), + projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } .to_predicate(tcx), @@ -512,9 +515,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx, goal, ty::ProjectionPredicate { - projection_ty: ecx - .tcx() - .mk_alias_ty(goal.predicate.def_id(), [self_ty, generator.resume_ty()]), + projection_ty: ty::AliasTy::new( + ecx.tcx(), + goal.predicate.def_id(), + [self_ty, generator.resume_ty()], + ), term, } .to_predicate(tcx), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 78f7f915f726..66529b67c17b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -313,6 +313,18 @@ pub trait TypeErrCtxtExt<'tcx> { predicate: ty::Predicate<'tcx>, call_hir_id: HirId, ); + + fn look_for_iterator_item_mistakes( + &self, + assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], + typeck_results: &TypeckResults<'tcx>, + type_diffs: &[TypeError<'tcx>], + param_env: ty::ParamEnv<'tcx>, + path_segment: &hir::PathSegment<'_>, + args: &[hir::Expr<'_>], + err: &mut Diagnostic, + ); + fn point_at_chain( &self, expr: &hir::Expr<'_>, @@ -321,6 +333,7 @@ pub trait TypeErrCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, err: &mut Diagnostic, ); + fn probe_assoc_types_at_expr( &self, type_diffs: &[TypeError<'tcx>], @@ -3612,6 +3625,109 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + fn look_for_iterator_item_mistakes( + &self, + assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], + typeck_results: &TypeckResults<'tcx>, + type_diffs: &[TypeError<'tcx>], + param_env: ty::ParamEnv<'tcx>, + path_segment: &hir::PathSegment<'_>, + args: &[hir::Expr<'_>], + err: &mut Diagnostic, + ) { + let tcx = self.tcx; + // Special case for iterator chains, we look at potential failures of `Iterator::Item` + // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`. + for entry in assocs_in_this_method { + let Some((_span, (def_id, ty))) = entry else { + continue; + }; + for diff in type_diffs { + let Sorts(expected_found) = diff else { + continue; + }; + if tcx.is_diagnostic_item(sym::IteratorItem, *def_id) + && path_segment.ident.name == sym::map + && self.can_eq(param_env, expected_found.found, *ty) + && let [arg] = args + && let hir::ExprKind::Closure(closure) = arg.kind + { + let body = tcx.hir().body(closure.body); + if let hir::ExprKind::Block(block, None) = body.value.kind + && let None = block.expr + && let [.., stmt] = block.stmts + && let hir::StmtKind::Semi(expr) = stmt.kind + // FIXME: actually check the expected vs found types, but right now + // the expected is a projection that we need to resolve. + // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) + && expected_found.found.is_unit() + { + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(stmt.span.hi()), + "consider removing this semicolon", + String::new(), + Applicability::MachineApplicable, + ); + } + let expr = if let hir::ExprKind::Block(block, None) = body.value.kind + && let Some(expr) = block.expr + { + expr + } else { + body.value + }; + if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind + && path_segment.ident.name == sym::clone + && let Some(expr_ty) = typeck_results.expr_ty_opt(expr) + && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr) + && self.can_eq(param_env, expr_ty, rcvr_ty) + && let ty::Ref(_, ty, _) = expr_ty.kind() + { + err.span_label( + span, + format!( + "this method call is cloning the reference `{expr_ty}`, not \ + `{ty}` which doesn't implement `Clone`", + ), + ); + let ty::Param(..) = ty.kind() else { + continue; + }; + let hir = tcx.hir(); + let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id); + + let pred = ty::Binder::dummy(ty::TraitPredicate { + trait_ref: ty::TraitRef::from_lang_item( + tcx, + LangItem::Clone, + span, + [*ty], + ), + polarity: ty::ImplPolarity::Positive, + }); + let Some(generics) = node.generics() else { + continue; + }; + let Some(body_id) = node.body_id() else { + continue; + }; + suggest_restriction( + tcx, + hir.body_owner_def_id(body_id), + &generics, + &format!("type parameter `{ty}`"), + err, + node.fn_sig(), + None, + pred, + None, + ); + } + } + } + } + } + fn point_at_chain( &self, expr: &hir::Expr<'_>, @@ -3631,13 +3747,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), ); - while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind { + while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind { // Point at every method call in the chain with the resulting type. // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^ ^^^^^^^^^^^ expr = rcvr_expr; let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); + self.look_for_iterator_item_mistakes( + &assocs_in_this_method, + typeck_results, + &type_diffs, + param_env, + path_segment, + args, + err, + ); assocs.push(assocs_in_this_method); prev_ty = self.resolve_vars_if_possible( typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), @@ -3812,7 +3937,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // This corresponds to `::Item = _`. let projection = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty: self.tcx.mk_alias_ty(proj.def_id, args), + projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args), term: ty_var.into(), }), )); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1020144a01b2..640bd3fad7ca 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -60,10 +60,7 @@ pub trait TypeErrCtxtExt<'tcx> { suggest_increasing_limit: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; fn report_overflow_error( &self, @@ -73,10 +70,7 @@ pub trait TypeErrCtxtExt<'tcx> { mutate: impl FnOnce(&mut Diagnostic), ) -> ! where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug; + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; @@ -227,10 +221,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mutate: impl FnOnce(&mut Diagnostic), ) -> ! where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, { let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); mutate(&mut err); @@ -247,10 +238,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { suggest_increasing_limit: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> where - T: fmt::Display - + TypeFoldable> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, + T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, { let predicate = self.resolve_vars_if_possible(predicate.clone()); let mut pred_str = predicate.to_string(); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index da357dac415f..55b5604b16b5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,6 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::GenericArgsRef; @@ -626,27 +625,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, - ty::PredicateKind::AliasRelate(..) - if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) => - { - ProcessResult::Unchanged + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } - ty::PredicateKind::AliasRelate(a, b, relate) => match relate { - ty::AliasRelationDirection::Equate => match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, a, b) - { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - )), - }, - ty::AliasRelationDirection::Subtype => { - bug!("AliasRelate with subtyping is only used for new solver") - } - }, ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( DefineOpaqueTypes::No, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 175cc2b116b7..b923926d28df 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2072,7 +2072,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( }; ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), term: ty.into(), } }); @@ -2116,7 +2116,7 @@ fn confirm_future_candidate<'cx, 'tcx>( debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), term: return_ty.into(), } }); @@ -2172,7 +2172,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( }; let predicate = - ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, args), term }; + ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(tcx, item_def_id, args), term }; confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) .with_addl_obligations(obligations) @@ -2245,7 +2245,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( flag, ) .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.args), + projection_ty: ty::AliasTy::new(tcx, fn_once_output_def_id, trait_ref.args), term: ret_type.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 f08cf6cef5b3..a8001577bcd5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -704,7 +704,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let ty = traits::normalize_projection_type( self, param_env, - tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.args), + ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args), cause.clone(), 0, // We're *intentionally* throwing these away, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 97366a93e311..940ceca50d2d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,7 +38,6 @@ use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fold::BottomUpFolder; @@ -1005,27 +1004,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } - ty::PredicateKind::AliasRelate(..) - if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) => - { - Ok(EvaluatedToAmbig) + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } - ty::PredicateKind::AliasRelate(a, b, relate) => match relate { - ty::AliasRelationDirection::Equate => match self - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, a, b) - { - Ok(inf_ok) => self.evaluate_predicates_recursively( - previous_stack, - inf_ok.into_obligations(), - ), - Err(_) => Ok(EvaluatedToErr), - }, - ty::AliasRelationDirection::Subtype => { - bug!("AliasRelate subtyping is only used for new solver") - } - }, ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index aa6fe7d24196..c2b2730c328f 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_transmute" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5df068de1f84..0a35e8d3a90c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,7 +1,9 @@ #![feature(associated_type_defaults)] #![feature(fmt_helpers_for_derive)] +#![feature(get_mut_unchecked)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(unwrap_infallible)] #![deny(rustc::untranslatable_diagnostic)] @@ -40,35 +42,41 @@ pub use ty_info::*; pub trait HashStableContext {} pub trait Interner: Sized { + type DefId: Clone + Debug + Hash + Ord; type AdtDef: Clone + Debug + Hash + Ord; - type GenericArgsRef: Clone + + type GenericArgs: Clone + DebugWithInfcx + Hash + Ord + IntoIterator; type GenericArg: Clone + DebugWithInfcx + Hash + Ord; - type DefId: Clone + Debug + Hash + Ord; + type Binder; - type Ty: Clone + DebugWithInfcx + Hash + Ord; - type Const: Clone + DebugWithInfcx + Hash + Ord; - type Region: Clone + DebugWithInfcx + Hash + Ord; + + // Predicates type Predicate; + type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; + type TypeAndMut: Clone + Debug + Hash + Ord; - type Mutability: Clone + Debug + Hash + Ord; - type Movability: Clone + Debug + Hash + Ord; - type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; - type ListBinderExistentialPredicate: Clone + DebugWithInfcx + Hash + Ord; - type BinderListTy: Clone + DebugWithInfcx + Hash + Ord; - type ListTy: Clone + Debug + Hash + Ord + IntoIterator; + + // Kinds of tys + type Ty: Clone + DebugWithInfcx + Hash + Ord; + type Tys: Clone + Debug + Hash + Ord + IntoIterator; type AliasTy: Clone + DebugWithInfcx + Hash + Ord; type ParamTy: Clone + Debug + Hash + Ord; type BoundTy: Clone + Debug + Hash + Ord; - type PlaceholderType: Clone + Debug + Hash + Ord; + type PlaceholderTy: Clone + Debug + Hash + Ord; type InferTy: Clone + DebugWithInfcx + Hash + Ord; + + // Things stored inside of tys type ErrorGuaranteed: Clone + Debug + Hash + Ord; - type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; + type BoundExistentialPredicates: Clone + DebugWithInfcx + Hash + Ord; + type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; type AllocId: Clone + Debug + Hash + Ord; + // Kinds of consts + type Const: Clone + DebugWithInfcx + Hash + Ord; type InferConst: Clone + DebugWithInfcx + Hash + Ord; type AliasConst: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderConst: Clone + Debug + Hash + Ord; @@ -77,14 +85,15 @@ pub trait Interner: Sized { type ValueConst: Clone + Debug + Hash + Ord; type ExprConst: Clone + DebugWithInfcx + Hash + Ord; + // Kinds of regions + type Region: Clone + DebugWithInfcx + Hash + Ord; type EarlyBoundRegion: Clone + Debug + Hash + Ord; type BoundRegion: Clone + Debug + Hash + Ord; type FreeRegion: Clone + Debug + Hash + Ord; - type RegionVid: Clone + DebugWithInfcx + Hash + Ord; + type InferRegion: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderRegion: Clone + Debug + Hash + Ord; - fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability); - fn mutability_is_mut(mutbl: Self::Mutability) -> bool; + fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability); } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index f1037fe0bafa..93b3674b51a5 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -5,12 +5,12 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex}; -use rustc_data_structures::functor::IdFunctor; use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; use core::fmt; use std::marker::PhantomData; +use std::mem; use std::ops::ControlFlow; /////////////////////////////////////////////////////////////////////////// @@ -108,8 +108,39 @@ impl, E: TypeVisitable> TypeVisitable for } impl> TypeFoldable for Lrc { - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|value| value.try_fold_with(folder)) + fn try_fold_with>(mut self, folder: &mut F) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Lrc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Lrc::make_mut` will accomplish (by + // allocating a new `Lrc` and cloning the `T` only if required). + // This is done *before* casting to `Lrc>` so that + // panicking during `make_mut` does not leak the `T`. + Lrc::make_mut(&mut self); + + // Casting to `Lrc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Lrc::into_raw(self).cast::>(); + let mut unique = Lrc::from_raw(ptr); + + // Call to `Lrc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Lrc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = mem::ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = mem::ManuallyDrop::new(folded); + + // Cast back to `Lrc`. + Ok(Lrc::from_raw(Lrc::into_raw(unique).cast())) + } } } @@ -120,8 +151,9 @@ impl> TypeVisitable for Lrc { } impl> TypeFoldable for Box { - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|value| value.try_fold_with(folder)) + fn try_fold_with>(mut self, folder: &mut F) -> Result { + *self = (*self).try_fold_with(folder)?; + Ok(self) } } @@ -133,7 +165,7 @@ impl> TypeVisitable for Box { impl> TypeFoldable for Vec { fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|t| t.try_fold_with(folder)) + self.into_iter().map(|t| t.try_fold_with(folder)).collect() } } @@ -161,7 +193,7 @@ impl> TypeVisitable for Box<[T]> { impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_map_id(|x| x.try_fold_with(folder)) + self.raw.try_fold_with(folder).map(IndexVec::from_raw) } } @@ -176,7 +208,7 @@ impl, Ix: Idx> TypeVisitable for IndexVec { fn universe_of_ty(&self, ty: I::InferTy) -> Option; - fn universe_of_lt(&self, lt: I::RegionVid) -> Option; + fn universe_of_lt(&self, lt: I::InferRegion) -> Option; fn universe_of_ct(&self, ct: I::InferConst) -> Option; } @@ -187,7 +219,7 @@ impl InferCtxtLike for core::convert::Infallible { fn universe_of_ct(&self, _ct: ::InferConst) -> Option { match *self {} } - fn universe_of_lt(&self, _lt: ::RegionVid) -> Option { + fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { match *self {} } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 091b51440a6e..5ca77701eb01 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -18,6 +18,68 @@ use self::TyKind::*; use rustc_data_structures::stable_hasher::HashStable; use rustc_serialize::{Decodable, Decoder, Encodable}; +/// The movability of a generator / closure literal: +/// whether a generator contains self-references, causing it to be `!Unpin`. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] +#[derive(HashStable_Generic)] +pub enum Movability { + /// May contain self-references, `!Unpin`. + Static, + /// Must not contain self-references, `Unpin`. + Movable, +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum Mutability { + // N.B. Order is deliberate, so that Not < Mut + Not, + Mut, +} + +impl Mutability { + pub fn invert(self) -> Self { + match self { + Mutability::Mut => Mutability::Not, + Mutability::Not => Mutability::Mut, + } + } + + /// Returns `""` (empty string) or `"mut "` depending on the mutability. + pub fn prefix_str(self) -> &'static str { + match self { + Mutability::Mut => "mut ", + Mutability::Not => "", + } + } + + /// Returns `"&"` or `"&mut "` depending on the mutability. + pub fn ref_prefix_str(self) -> &'static str { + match self { + Mutability::Not => "&", + Mutability::Mut => "&mut ", + } + } + + /// Returns `""` (empty string) or `"mutably "` depending on the mutability. + pub fn mutably_str(self) -> &'static str { + match self { + Mutability::Not => "", + Mutability::Mut => "mutably ", + } + } + + /// Return `true` if self is mutable + pub fn is_mut(self) -> bool { + matches!(self, Self::Mut) + } + + /// Return `true` if self is **not** mutable + pub fn is_not(self) -> bool { + matches!(self, Self::Not) + } +} + /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] @@ -79,7 +141,7 @@ pub enum TyKind { /// /// Note that generic parameters in fields only get lazily substituted /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`. - Adt(I::AdtDef, I::GenericArgsRef), + Adt(I::AdtDef, I::GenericArgs), /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. Foreign(I::DefId), @@ -98,7 +160,7 @@ pub enum TyKind { /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - Ref(I::Region, I::Ty, I::Mutability), + Ref(I::Region, I::Ty, Mutability), /// The anonymous type of a function declaration/definition. Each /// function has a unique type. @@ -111,7 +173,7 @@ pub enum TyKind { /// fn foo() -> i32 { 1 } /// let bar = foo; // bar: fn() -> i32 {foo} /// ``` - FnDef(I::DefId, I::GenericArgsRef), + FnDef(I::DefId, I::GenericArgs), /// A pointer to a function. Written as `fn() -> i32`. /// @@ -127,21 +189,21 @@ pub enum TyKind { FnPtr(I::PolyFnSig), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. - Dynamic(I::ListBinderExistentialPredicate, I::Region, DynKind), + Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), /// The anonymous type of a closure. Used to represent the type of `|a| a`. /// /// Closure args contain both the - potentially substituted - generic parameters /// of its parent and some synthetic parameters. See the documentation for /// `ClosureArgs` for more details. - Closure(I::DefId, I::GenericArgsRef), + Closure(I::DefId, I::GenericArgs), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. /// /// For more info about generator args, visit the documentation for /// `GeneratorArgs`. - Generator(I::DefId, I::GenericArgsRef, I::Movability), + Generator(I::DefId, I::GenericArgs, Movability), /// A type representing the types stored inside a generator. /// This should only appear as part of the `GeneratorArgs`. @@ -167,13 +229,13 @@ pub enum TyKind { /// } /// # ; /// ``` - GeneratorWitness(I::DefId, I::GenericArgsRef), + GeneratorWitness(I::DefId, I::GenericArgs), /// The never type `!`. Never, /// A tuple type. For example, `(i32, bool)`. - Tuple(I::ListTy), + Tuple(I::Tys), /// A projection, opaque type, weak type alias, or inherent associated type. /// All of these types are represented as pairs of def-id and args, and can @@ -209,7 +271,7 @@ pub enum TyKind { /// to the bound variable's index from the binder from which it was instantiated), /// and `U` is the universe index in which it is instantiated, or totally omitted /// if the universe index is zero. - Placeholder(I::PlaceholderType), + Placeholder(I::PlaceholderTy), /// A type variable used during type checking. /// @@ -506,15 +568,15 @@ impl DebugWithInfcx for TyKind { Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), RawPtr(p) => { let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone()); - match I::mutability_is_mut(mutbl) { - true => write!(f, "*mut "), - false => write!(f, "*const "), + match mutbl { + Mutability::Mut => write!(f, "*mut "), + Mutability::Not => write!(f, "*const "), }?; write!(f, "{:?}", &this.wrap(ty)) } - Ref(r, t, m) => match I::mutability_is_mut(m.clone()) { - true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), - false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), + Ref(r, t, m) => match m { + Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), + Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), }, FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), @@ -567,22 +629,19 @@ impl Encodable for TyKind where I::ErrorGuaranteed: Encodable, I::AdtDef: Encodable, - I::GenericArgsRef: Encodable, + I::GenericArgs: Encodable, I::DefId: Encodable, I::Ty: Encodable, I::Const: Encodable, I::Region: Encodable, I::TypeAndMut: Encodable, - I::Mutability: Encodable, - I::Movability: Encodable, I::PolyFnSig: Encodable, - I::ListBinderExistentialPredicate: Encodable, - I::BinderListTy: Encodable, - I::ListTy: Encodable, + I::BoundExistentialPredicates: Encodable, + I::Tys: Encodable, I::AliasTy: Encodable, I::ParamTy: Encodable, I::BoundTy: Encodable, - I::PlaceholderType: Encodable, + I::PlaceholderTy: Encodable, I::InferTy: Encodable, I::PredicateKind: Encodable, I::AllocId: Encodable, @@ -682,23 +741,20 @@ impl> Decodable for TyKind where I::ErrorGuaranteed: Decodable, I::AdtDef: Decodable, - I::GenericArgsRef: Decodable, + I::GenericArgs: Decodable, I::DefId: Decodable, I::Ty: Decodable, I::Const: Decodable, I::Region: Decodable, I::TypeAndMut: Decodable, - I::Mutability: Decodable, - I::Movability: Decodable, I::PolyFnSig: Decodable, - I::ListBinderExistentialPredicate: Decodable, - I::BinderListTy: Decodable, - I::ListTy: Decodable, + I::BoundExistentialPredicates: Decodable, + I::Tys: Decodable, I::AliasTy: Decodable, I::ParamTy: Decodable, I::AliasTy: Decodable, I::BoundTy: Decodable, - I::PlaceholderType: Decodable, + I::PlaceholderTy: Decodable, I::InferTy: Decodable, I::PredicateKind: Decodable, I::AllocId: Decodable, @@ -748,21 +804,18 @@ impl HashStable for TyKind where I::AdtDef: HashStable, I::DefId: HashStable, - I::GenericArgsRef: HashStable, + I::GenericArgs: HashStable, I::Ty: HashStable, I::Const: HashStable, I::TypeAndMut: HashStable, I::PolyFnSig: HashStable, - I::ListBinderExistentialPredicate: HashStable, + I::BoundExistentialPredicates: HashStable, I::Region: HashStable, - I::Movability: HashStable, - I::Mutability: HashStable, - I::BinderListTy: HashStable, - I::ListTy: HashStable, + I::Tys: HashStable, I::AliasTy: HashStable, I::BoundTy: HashStable, I::ParamTy: HashStable, - I::PlaceholderType: HashStable, + I::PlaceholderTy: HashStable, I::InferTy: HashStable, I::ErrorGuaranteed: HashStable, { @@ -1204,7 +1257,7 @@ pub enum RegionKind { ReStatic, /// A region variable. Should not exist outside of type inference. - ReVar(I::RegionVid), + ReVar(I::InferRegion), /// A placeholder region -- basically, the higher-ranked version of `ReFree`. /// Should not exist outside of type inference. @@ -1239,7 +1292,7 @@ where I::EarlyBoundRegion: Copy, I::BoundRegion: Copy, I::FreeRegion: Copy, - I::RegionVid: Copy, + I::InferRegion: Copy, I::PlaceholderRegion: Copy, I::ErrorGuaranteed: Copy, { @@ -1379,7 +1432,7 @@ where I::EarlyBoundRegion: Encodable, I::BoundRegion: Encodable, I::FreeRegion: Encodable, - I::RegionVid: Encodable, + I::InferRegion: Encodable, I::PlaceholderRegion: Encodable, { fn encode(&self, e: &mut E) { @@ -1414,7 +1467,7 @@ where I::EarlyBoundRegion: Decodable, I::BoundRegion: Decodable, I::FreeRegion: Decodable, - I::RegionVid: Decodable, + I::InferRegion: Decodable, I::PlaceholderRegion: Decodable, I::ErrorGuaranteed: Decodable, { @@ -1445,7 +1498,7 @@ where I::EarlyBoundRegion: HashStable, I::BoundRegion: HashStable, I::FreeRegion: HashStable, - I::RegionVid: HashStable, + I::InferRegion: HashStable, I::PlaceholderRegion: HashStable, { #[inline] diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs new file mode 100644 index 000000000000..12ac8f1ca65a --- /dev/null +++ b/compiler/stable_mir/src/error.rs @@ -0,0 +1,69 @@ +//! When things go wrong, we need some error handling. +//! There are a few different types of errors in StableMIR: +//! +//! - [CompilerError]: This represents errors that can be raised when invoking the compiler. +//! - [Error]: Generic error that represents the reason why a request that could not be fulfilled. + +use std::fmt::{Debug, Display, Formatter}; +use std::{error, fmt}; + +/// An error type used to represent an error that has already been reported by the compiler. +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum CompilerError { + /// Internal compiler error (I.e.: Compiler crashed). + ICE, + /// Compilation failed. + CompilationFailed, + /// Compilation was interrupted. + Interrupted(T), + /// Compilation skipped. This happens when users invoke rustc to retrieve information such as + /// --version. + Skipped, +} + +/// A generic error to represent an API request that cannot be fulfilled. +#[derive(Debug)] +pub struct Error(String); + +impl Error { + pub(crate) fn new(msg: String) -> Self { + Self(msg) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl Display for CompilerError +where + T: Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + CompilerError::ICE => write!(f, "Internal Compiler Error"), + CompilerError::CompilationFailed => write!(f, "Compilation Failed"), + CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason}"), + CompilerError::Skipped => write!(f, "Compilation Skipped"), + } + } +} + +impl Debug for CompilerError +where + T: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + CompilerError::ICE => write!(f, "Internal Compiler Error"), + CompilerError::CompilationFailed => write!(f, "Compilation Failed"), + CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason:?}"), + CompilerError::Skipped => write!(f, "Compilation Skipped"), + } + } +} + +impl error::Error for Error {} +impl error::Error for CompilerError where T: Display + Debug {} diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index a3b05f2435eb..59af3f64ad34 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -17,6 +17,8 @@ //! The goal is to eventually be published on //! [crates.io](https://crates.io). +use crate::mir::mono::InstanceDef; +use crate::mir::Body; use std::cell::Cell; use std::fmt; use std::fmt::Debug; @@ -29,11 +31,15 @@ use self::ty::{ #[macro_use] extern crate scoped_tls; +pub mod error; pub mod fold; pub mod mir; pub mod ty; pub mod visitor; +pub use error::*; +use mir::mono::Instance; + /// Use String for now but we should replace it. pub type Symbol = String; @@ -85,20 +91,6 @@ pub type TraitDecls = Vec; /// A list of impl trait decls. pub type ImplTraitDecls = Vec; -/// An error type used to represent an error that has already been reported by the compiler. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum CompilerError { - /// Internal compiler error (I.e.: Compiler crashed). - ICE, - /// Compilation failed. - CompilationFailed, - /// Compilation was interrupted. - Interrupted(T), - /// Compilation skipped. This happens when users invoke rustc to retrieve information such as - /// --version. - Skipped, -} - /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { @@ -113,7 +105,7 @@ pub type Filename = Opaque; /// Holds information about an item in the crate. /// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to /// use this item. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct CrateItem(pub DefId); impl CrateItem { @@ -132,6 +124,10 @@ impl CrateItem { pub fn kind(&self) -> DefKind { with(|cx| cx.def_kind(self.0)) } + + pub fn requires_monomorphization(&self) -> bool { + with(|cx| cx.requires_monomorphization(self.0)) + } } /// Return the function where execution starts if the current @@ -220,6 +216,23 @@ pub trait Context { /// Create a new `Ty` from scratch without information from rustc. fn mk_ty(&mut self, kind: TyKind) -> Ty; + + /// Get the body of an Instance. + /// FIXME: Monomorphize the body. + fn instance_body(&mut self, instance: InstanceDef) -> Body; + + /// Get the instance type with generic substitutions applied and lifetimes erased. + fn instance_ty(&mut self, instance: InstanceDef) -> Ty; + + /// Get the instance. + fn instance_def_id(&mut self, instance: InstanceDef) -> DefId; + + /// Convert a non-generic crate item into an instance. + /// This function will panic if the item is generic. + fn mono_instance(&mut self, item: CrateItem) -> Instance; + + /// Item requires monomorphization. + fn requires_monomorphization(&self, def_id: DefId) -> bool; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs index a9dbc3463f80..3138bb1ec832 100644 --- a/compiler/stable_mir/src/mir.rs +++ b/compiler/stable_mir/src/mir.rs @@ -1,3 +1,4 @@ mod body; +pub mod mono; pub use body::*; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs new file mode 100644 index 000000000000..d8e8ccb04548 --- /dev/null +++ b/compiler/stable_mir/src/mir/mono.rs @@ -0,0 +1,89 @@ +use crate::mir::Body; +use crate::ty::{IndexedVal, Ty}; +use crate::{with, CrateItem, DefId, Error, Opaque}; +use std::fmt::Debug; + +#[derive(Clone, Debug)] +pub enum MonoItem { + Fn(Instance), + Static(StaticDef), + GlobalAsm(Opaque), +} + +#[derive(Copy, Clone, Debug)] +pub struct Instance { + /// The type of instance. + pub kind: InstanceKind, + /// An ID used to get the instance definition from the compiler. + /// Do not use this field directly. + pub def: InstanceDef, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum InstanceKind { + /// A user defined item. + Item, + /// A compiler intrinsic function. + Intrinsic, + /// A virtual function definition stored in a VTable. + Virtual, + /// A compiler generated shim. + Shim, +} + +impl Instance { + /// Get the body of an Instance. The body will be eagerly monomorphized. + pub fn body(&self) -> Body { + with(|context| context.instance_body(self.def)) + } + + /// Get the instance type with generic substitutions applied and lifetimes erased. + pub fn ty(&self) -> Ty { + with(|context| context.instance_ty(self.def)) + } +} + +/// Try to convert a crate item into an instance. +/// The item cannot be generic in order to be converted into an instance. +impl TryFrom for Instance { + type Error = crate::Error; + + fn try_from(item: CrateItem) -> Result { + with(|context| { + if !context.requires_monomorphization(item.0) { + Ok(context.mono_instance(item)) + } else { + Err(Error::new("Item requires monomorphization".to_string())) + } + }) + } +} + +/// Try to convert an instance into a crate item. +/// Only user defined instances can be converted. +impl TryFrom for CrateItem { + type Error = crate::Error; + + fn try_from(value: Instance) -> Result { + if value.kind == InstanceKind::Item { + Ok(CrateItem(with(|context| context.instance_def_id(value.def)))) + } else { + Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind))) + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct InstanceDef(usize); + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct StaticDef(pub DefId); + +impl IndexedVal for InstanceDef { + fn to_val(index: usize) -> Self { + InstanceDef(index) + } + fn to_index(&self) -> usize { + self.0 + } +} diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 01b03de6acb5..625b67a79ad0 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -530,6 +530,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. #[cfg(not(no_global_oom_handling))] +#[inline(never)] fn capacity_overflow() -> ! { panic!("capacity overflow"); } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 963545a2eb2d..03243e31348e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -219,7 +219,6 @@ #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] -#![feature(effects)] #![feature(exhaustive_patterns)] #![feature(extern_types)] #![feature(fundamental)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bdaeea666221..12de349d22bc 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -959,6 +959,7 @@ impl Option { /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); /// ``` #[inline] + #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap_or_else(self, f: F) -> T where diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index de41bd1a1167..073488817c48 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -79,6 +79,40 @@ //! //! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm //! +//! # Atomic accesses to read-only memory +//! +//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting +//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only +//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since +//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault +//! on read-only memory. +//! +//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in +//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write +//! will cause a page fault. In particular, an `&u128` reference that points to memory that is +//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory +//! is read-write; the only exceptions are memory created by `const` items or `static` items without +//! interior mutability, and memory that was specifically marked as read-only by the operating +//! system via platform-specific APIs. +//! +//! As an exception from the general rule stated above, "sufficiently small" atomic loads with +//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not +//! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies +//! depending on the target: +//! +//! | `target_arch` | Size limit | +//! |---------------|---------| +//! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | +//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes | +//! +//! Atomics loads that are larger than this limit as well as atomic loads with ordering other +//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be +//! read-only under certain conditions, but that is not a stable guarantee and should not be relied +//! upon. +//! +//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an +//! acquire fence instead. +//! //! # Examples //! //! A simple spinlock: diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 08858dd92be0..54eb6627c012 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -63,7 +63,7 @@ pub unsafe fn panic(data: Box) -> u32 { _uwe: uw::_Unwind_Exception { exception_class: rust_exception_class(), exception_cleanup, - private: [0; uw::unwinder_private_data_size], + private: [core::ptr::null(); uw::unwinder_private_data_size], }, canary: &CANARY, cause: data, diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 81106d6c62c3..24f2bdcf4217 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -97,14 +97,14 @@ impl BorrowedFd<'_> { // We want to atomically duplicate this file descriptor and set the // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This // is a POSIX flag that was added to Linux in 2.6.24. - #[cfg(not(target_os = "espidf"))] + #[cfg(not(any(target_os = "espidf", target_os = "vita")))] let cmd = libc::F_DUPFD_CLOEXEC; // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics // will never be supported, as this is a bare metal framework with // no capabilities for multi-process execution. While F_DUPFD is also // not supported yet, it might be (currently it returns ENOSYS). - #[cfg(target_os = "espidf")] + #[cfg(any(target_os = "espidf", target_os = "vita"))] let cmd = libc::F_DUPFD; // Avoid using file descriptors below 3 as they are used for stdio @@ -119,7 +119,7 @@ impl BorrowedFd<'_> { pub fn try_clone_to_owned(&self) -> crate::io::Result { Err(crate::io::const_io_error!( crate::io::ErrorKind::Unsupported, - "operation not supported on WASI yet", + "operation not supported on this platform", )) } } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index f1eeb75be7c4..5c83f72f3c1a 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -155,6 +155,7 @@ fn lang_start_internal( } #[cfg(not(test))] +#[inline(never)] #[lang = "start"] fn lang_start( main: fn() -> T, diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index a564f1698bae..bd8b493d65aa 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -56,6 +56,12 @@ impl Socket { unimplemented!() } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; + Ok(()) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { diff --git a/library/std/src/sys/hermit/thread_local_dtor.rs b/library/std/src/sys/hermit/thread_local_dtor.rs index 613266b9530a..98adaf4bff1a 100644 --- a/library/std/src/sys/hermit/thread_local_dtor.rs +++ b/library/std/src/sys/hermit/thread_local_dtor.rs @@ -5,23 +5,25 @@ // The this solution works like the implementation of macOS and // doesn't additional OS support -use crate::mem; +use crate::cell::RefCell; #[thread_local] -static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DTORS: RefCell> = RefCell::new(Vec::new()); pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - let list = &mut DTORS; - list.push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } } // every thread call this function to run through all possible destructors pub unsafe fn run_dtors() { - let mut list = mem::take(&mut DTORS); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { dtor(ptr); } - list = mem::take(&mut DTORS); + list = DTORS.take(); } } diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index 79624703a4cf..a78084de0fae 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -1,6 +1,7 @@ //! Parsing of GCC-style Language-Specific Data Area (LSDA) //! For details see: //! * +//! * //! * //! * //! * @@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80; #[derive(Copy, Clone)] pub struct EHContext<'a> { - pub ip: usize, // Current instruction pointer - pub func_start: usize, // Address of the current function - pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section - pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section + pub ip: *const u8, // Current instruction pointer + pub func_start: *const u8, // Pointer to the current function + pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section + pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section } +/// Landing pad. +type LPad = *const u8; pub enum EHAction { None, - Cleanup(usize), - Catch(usize), - Filter(usize), + Cleanup(LPad), + Catch(LPad), + Filter(LPad), Terminate, } @@ -81,22 +84,24 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let ip = context.ip; if !USING_SJLJ_EXCEPTIONS { + // read the callsite table while reader.ptr < action_table { - let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; - let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; - let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + // these are offsets rather than pointers; + let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; let cs_action_entry = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. - if ip < func_start + cs_start { + if ip < func_start.wrapping_add(cs_start) { break; } - if ip < func_start + cs_start + cs_len { + if ip < func_start.wrapping_add(cs_start + cs_len) { if cs_lpad == 0 { return Ok(EHAction::None); } else { - let lpad = lpad_base + cs_lpad; - return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); + let lpad = lpad_base.wrapping_add(cs_lpad); + return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); } } } @@ -106,12 +111,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result // SjLj version: // The "IP" is an index into the call-site table, with two exceptions: // -1 means 'no-action', and 0 means 'terminate'. - match ip as isize { + match ip.addr() as isize { -1 => return Ok(EHAction::None), 0 => return Ok(EHAction::Terminate), _ => (), } - let mut idx = ip; + let mut idx = ip.addr(); loop { let cs_lpad = reader.read_uleb128(); let cs_action_entry = reader.read_uleb128(); @@ -119,17 +124,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result if idx == 0 { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. - let lpad = (cs_lpad + 1) as usize; - return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); + // FIXME(strict provenance) + let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize); + return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); } } } } unsafe fn interpret_cs_action( - action_table: *mut u8, + action_table: *const u8, cs_action_entry: u64, - lpad: usize, + lpad: LPad, ) -> EHAction { if cs_action_entry == 0 { // If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these @@ -138,7 +144,7 @@ unsafe fn interpret_cs_action( } else { // If lpad != 0 and cs_action_entry != 0, we have to check ttype_index. // If ttype_index == 0 under the condition, we take cleanup action. - let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1); + let action_record = action_table.offset(cs_action_entry as isize - 1); let mut action_reader = DwarfReader::new(action_record); let ttype_index = action_reader.read_sleb128(); if ttype_index == 0 { @@ -157,22 +163,24 @@ fn round_up(unrounded: usize, align: usize) -> Result { if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) } } -unsafe fn read_encoded_pointer( - reader: &mut DwarfReader, - context: &EHContext<'_>, - encoding: u8, -) -> Result { - if encoding == DW_EH_PE_omit { +/// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`. +/// +/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. +/// In addition the upper ("application") part must be zero. +/// +/// # Errors +/// Returns `Err` if `encoding` +/// * is not a valid DWARF Exception Header Encoding, +/// * is `DW_EH_PE_omit`, or +/// * has a non-zero application part. +/// +/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html +unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result { + if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 { return Err(()); } - - // DW_EH_PE_aligned implies it's an absolute pointer value - if encoding == DW_EH_PE_aligned { - reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::())?); - return Ok(reader.read::()); - } - - let mut result = match encoding & 0x0F { + let result = match encoding & 0x0F { + // despite the name, LLVM also uses absptr for offsets instead of pointers DW_EH_PE_absptr => reader.read::(), DW_EH_PE_uleb128 => reader.read_uleb128() as usize, DW_EH_PE_udata2 => reader.read::() as usize, @@ -184,25 +192,66 @@ unsafe fn read_encoded_pointer( DW_EH_PE_sdata8 => reader.read::() as usize, _ => return Err(()), }; + Ok(result) +} - result += match encoding & 0x70 { - DW_EH_PE_absptr => 0, +/// Read a pointer from `reader` whose encoding is described by `encoding`. +/// +/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. +/// +/// # Errors +/// Returns `Err` if `encoding` +/// * is not a valid DWARF Exception Header Encoding, +/// * is `DW_EH_PE_omit`, or +/// * combines `DW_EH_PE_absptr` or `DW_EH_PE_aligned` application part with an integer encoding +/// (not `DW_EH_PE_absptr`) in the value format part. +/// +/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html +unsafe fn read_encoded_pointer( + reader: &mut DwarfReader, + context: &EHContext<'_>, + encoding: u8, +) -> Result<*const u8, ()> { + if encoding == DW_EH_PE_omit { + return Err(()); + } + + let base_ptr = match encoding & 0x70 { + DW_EH_PE_absptr => core::ptr::null(), // relative to address of the encoded value, despite the name - DW_EH_PE_pcrel => reader.ptr.expose_addr(), + DW_EH_PE_pcrel => reader.ptr, DW_EH_PE_funcrel => { - if context.func_start == 0 { + if context.func_start.is_null() { return Err(()); } context.func_start } DW_EH_PE_textrel => (*context.get_text_start)(), DW_EH_PE_datarel => (*context.get_data_start)(), + // aligned means the value is aligned to the size of a pointer + DW_EH_PE_aligned => { + reader.ptr = + reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?); + core::ptr::null() + } _ => return Err(()), }; + let mut ptr = if base_ptr.is_null() { + // any value encoding other than absptr would be nonsensical here; + // there would be no source of pointer provenance + if encoding & 0x0F != DW_EH_PE_absptr { + return Err(()); + } + reader.read::<*const u8>() + } else { + let offset = read_encoded_offset(reader, encoding & 0x0F)?; + base_ptr.wrapping_add(offset) + }; + if encoding & DW_EH_PE_indirect != 0 { - result = *ptr::from_exposed_addr::(result); + ptr = *(ptr.cast::<*const u8>()); } - Ok(result) + Ok(ptr) } diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 559d2c7db471..6f317131145a 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -38,7 +38,6 @@ use super::dwarf::eh::{self, EHAction, EHContext}; use crate::ffi::c_int; -use libc::uintptr_t; use unwind as uw; // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() @@ -160,9 +159,9 @@ cfg_if::cfg_if! { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, - exception_object as uintptr_t, + exception_object as uw::_Unwind_Ptr, ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); uw::_Unwind_SetIP(context, lpad); return uw::_URC_INSTALL_CONTEXT; } @@ -222,9 +221,9 @@ cfg_if::cfg_if! { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, - exception_object as uintptr_t, + exception_object.cast(), ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); uw::_Unwind_SetIP(context, lpad); uw::_URC_INSTALL_CONTEXT } diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 6adced787f3b..1eae0fc0642b 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -233,12 +233,15 @@ impl Socket { } } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + cvt(unsafe { netc::connect(self.0.raw(), addr.as_ptr(), len) })?; + Ok(()) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; - let r = unsafe { - let (addr, len) = addr.into_inner(); - cvt(netc::connect(self.0.raw(), addr.as_ptr(), len)) - }; + let r = self.connect(addr); self.set_nonblocking(false)?; match r { diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs index bad14bb37f72..26918a4fcb01 100644 --- a/library/std/src/sys/solid/thread_local_dtor.rs +++ b/library/std/src/sys/solid/thread_local_dtor.rs @@ -4,14 +4,13 @@ // Simplify dtor registration by using a list of destructors. use super::{abi, itron::task}; -use crate::cell::Cell; -use crate::mem; +use crate::cell::{Cell, RefCell}; #[thread_local] static REGISTERED: Cell = Cell::new(false); #[thread_local] -static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DTORS: RefCell> = RefCell::new(Vec::new()); pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { if !REGISTERED.get() { @@ -22,18 +21,20 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { REGISTERED.set(true); } - let list = unsafe { &mut DTORS }; - list.push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } } pub unsafe fn run_dtors() { - let mut list = mem::take(unsafe { &mut DTORS }); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { unsafe { dtor(ptr) }; } - list = mem::take(unsafe { &mut DTORS }); + list = DTORS.take(); } } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index f450d708dae6..ec861f9cb869 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -6,6 +6,7 @@ use crate::net::{Shutdown, SocketAddr}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::str; use crate::sys::fd::FileDesc; +use crate::sys::unix::IsMinusOne; use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; @@ -103,7 +104,7 @@ impl Socket { } } - #[cfg(not(any(target_os = "vxworks", target_os = "vita")))] + #[cfg(not(target_os = "vxworks"))] pub fn new_pair(fam: c_int, ty: c_int) -> io::Result<(Socket, Socket)> { unsafe { let mut fds = [0, 0]; @@ -135,11 +136,27 @@ impl Socket { } } - #[cfg(any(target_os = "vxworks", target_os = "vita"))] + #[cfg(target_os = "vxworks")] pub fn new_pair(_fam: c_int, _ty: c_int) -> io::Result<(Socket, Socket)> { unimplemented!() } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + loop { + let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) }; + if result.is_minus_one() { + let err = crate::sys::os::errno(); + match err { + libc::EINTR => continue, + libc::EISCONN => return Ok(()), + _ => return Err(io::Error::from_raw_os_error(err)), + } + } + return Ok(()); + } + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index a0117e1d165c..06399e8a2742 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -69,15 +69,14 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { // _tlv_atexit. #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - use crate::cell::Cell; - use crate::mem; + use crate::cell::{Cell, RefCell}; use crate::ptr; #[thread_local] static REGISTERED: Cell = Cell::new(false); #[thread_local] - static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); + static DTORS: RefCell> = RefCell::new(Vec::new()); if !REGISTERED.get() { _tlv_atexit(run_dtors, ptr::null_mut()); @@ -88,16 +87,18 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8); } - let list = &mut DTORS; - list.push((t, dtor)); + match DTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } unsafe extern "C" fn run_dtors(_: *mut u8) { - let mut list = mem::take(&mut DTORS); + let mut list = DTORS.take(); while !list.is_empty() { for (ptr, dtor) in list { dtor(ptr); } - list = mem::take(&mut DTORS); + list = DTORS.take(); } } } diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 4b7115f97c50..c29b863665f1 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -140,13 +140,15 @@ impl Socket { } } + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = addr.into_inner(); + let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; + cvt(result).map(drop) + } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; - let result = { - let (addr, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; - cvt(result).map(drop) - }; + let result = self.connect(addr); self.set_nonblocking(false)?; match result { diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 036d96596e9c..5eee4a9667ba 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -16,14 +16,19 @@ static HAS_DTORS: AtomicBool = AtomicBool::new(false); // Using a per-thread list avoids the problems in synchronizing global state. #[thread_local] #[cfg(target_thread_local)] -static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static DESTRUCTORS: crate::cell::RefCell> = + crate::cell::RefCell::new(Vec::new()); // Ensure this can never be inlined because otherwise this may break in dylibs. // See #44391. #[inline(never)] #[cfg(target_thread_local)] pub unsafe fn register_keyless_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - DESTRUCTORS.push((t, dtor)); + match DESTRUCTORS.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } + HAS_DTORS.store(true, Relaxed); } @@ -37,11 +42,17 @@ unsafe fn run_keyless_dtors() { // the case that this loop always terminates because we provide the // guarantee that a TLS key cannot be set after it is flagged for // destruction. - while let Some((ptr, dtor)) = DESTRUCTORS.pop() { + loop { + // Use a let-else binding to ensure the `RefCell` guard is dropped + // immediately. Otherwise, a panic would occur if a TLS destructor + // tries to access the list. + let Some((ptr, dtor)) = DESTRUCTORS.borrow_mut().pop() else { + break; + }; (dtor)(ptr); } // We're done so free the memory. - DESTRUCTORS = Vec::new(); + DESTRUCTORS.replace(Vec::new()); } type Key = c::DWORD; diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 4f5b17deaa2d..8712bd2eca76 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -226,9 +226,7 @@ impl TcpStream { init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; - - let (addr, len) = addr.into_inner(); - cvt_r(|| unsafe { c::connect(sock.as_raw(), addr.as_ptr(), len) })?; + sock.connect(addr)?; Ok(TcpStream { inner: sock }) } diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs index 844946eda031..98382fc6acc2 100644 --- a/library/std/src/sys_common/thread_local_dtor.rs +++ b/library/std/src/sys_common/thread_local_dtor.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "none")] #![allow(dead_code)] +use crate::cell::RefCell; use crate::ptr; use crate::sys_common::thread_local_key::StaticKey; @@ -28,17 +29,23 @@ pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut // flagged for destruction. static DTORS: StaticKey = StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; + // FIXME(joboet): integrate RefCell into pointer to avoid infinite recursion + // when the global allocator tries to register a destructor and just panic + // instead. + type List = RefCell>; if DTORS.get().is_null() { - let v: Box = Box::new(Vec::new()); + let v: Box = Box::new(RefCell::new(Vec::new())); DTORS.set(Box::into_raw(v) as *mut u8); } - let list: &mut List = &mut *(DTORS.get() as *mut List); - list.push((t, dtor)); + let list = &*(DTORS.get() as *const List); + match list.try_borrow_mut() { + Ok(mut dtors) => dtors.push((t, dtor)), + Err(_) => rtabort!("global allocator may not use TLS"), + } unsafe extern "C" fn run_dtors(mut ptr: *mut u8) { while !ptr.is_null() { - let list: Box = Box::from_raw(ptr as *mut List); + let list = Box::from_raw(ptr as *mut List).into_inner(); for (ptr, dtor) in list.into_iter() { dtor(ptr); } diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 94a91dd357c9..e86408a9ed2b 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -4,6 +4,7 @@ #![feature(staged_api)] #![feature(c_unwind)] #![feature(cfg_target_abi)] +#![feature(strict_provenance)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![allow(internal_features)] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index a2bfa8e96dd2..dba64aa74ce6 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -1,6 +1,6 @@ #![allow(nonstandard_style)] -use libc::{c_int, c_void, uintptr_t}; +use libc::{c_int, c_void}; #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq)] @@ -19,8 +19,8 @@ pub enum _Unwind_Reason_Code { pub use _Unwind_Reason_Code::*; pub type _Unwind_Exception_Class = u64; -pub type _Unwind_Word = uintptr_t; -pub type _Unwind_Ptr = uintptr_t; +pub type _Unwind_Word = *const u8; +pub type _Unwind_Ptr = *const u8; pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; @@ -214,7 +214,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe // On Android or ARM/Linux, these are implemented as macros: pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word { - let mut val: _Unwind_Word = 0; + let mut val: _Unwind_Word = core::ptr::null(); _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, &mut val as *mut _ as *mut c_void); val @@ -229,14 +229,14 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word { let val = _Unwind_GetGR(ctx, UNWIND_IP_REG); - (val & !1) as _Unwind_Word + val.map_addr(|v| v & !1) } pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) { // Propagate thumb bit to instruction pointer - let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1; - let value = value | thumb_state; + let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1; + let value = value.map_addr(|v| v | thumb_state); _Unwind_SetGR(ctx, UNWIND_IP_REG, value); } diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 006a992eb3c3..e236421b7f5f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -9,27 +9,27 @@ default-run = "bootstrap" build-metrics = ["sysinfo"] [lib] -path = "lib.rs" +path = "src/lib.rs" doctest = false [[bin]] name = "bootstrap" -path = "bin/main.rs" +path = "src/bin/main.rs" test = false [[bin]] name = "rustc" -path = "bin/rustc.rs" +path = "src/bin/rustc.rs" test = false [[bin]] name = "rustdoc" -path = "bin/rustdoc.rs" +path = "src/bin/rustdoc.rs" test = false [[bin]] name = "sccache-plus-cl" -path = "bin/sccache-plus-cl.rs" +path = "src/bin/sccache-plus-cl.rs" test = false [dependencies] diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs deleted file mode 100644 index b0a97b540ec7..000000000000 --- a/src/bootstrap/job.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! Job management on Windows for bootstrapping -//! -//! Most of the time when you're running a build system (e.g., make) you expect -//! Ctrl-C or abnormal termination to actually terminate the entire tree of -//! process in play, not just the one at the top. This currently works "by -//! default" on Unix platforms because Ctrl-C actually sends a signal to the -//! *process group* rather than the parent process, so everything will get torn -//! down. On Windows, however, this does not happen and Ctrl-C just kills the -//! parent process. -//! -//! To achieve the same semantics on Windows we use Job Objects to ensure that -//! all processes die at the same time. Job objects have a mode of operation -//! where when all handles to the object are closed it causes all child -//! processes associated with the object to be terminated immediately. -//! Conveniently whenever a process in the job object spawns a new process the -//! child will be associated with the job object as well. This means if we add -//! ourselves to the job object we create then everything will get torn down! -//! -//! Unfortunately most of the time the build system is actually called from a -//! python wrapper (which manages things like building the build system) so this -//! all doesn't quite cut it so far. To go the last mile we duplicate the job -//! object handle into our parent process (a python process probably) and then -//! close our own handle. This means that the only handle to the job object -//! resides in the parent python process, so when python dies the whole build -//! system dies (as one would probably expect!). -//! -//! Note that this module has a #[cfg(windows)] above it as none of this logic -//! is required on Unix. - -use crate::Build; -use std::env; -use std::ffi::c_void; -use std::io; -use std::mem; - -use windows::{ - core::PCWSTR, - Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE}, - Win32::System::Diagnostics::Debug::{SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE}, - Win32::System::JobObjects::{ - AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation, - SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, - }, - Win32::System::Threading::{ - GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE, - }, -}; - -pub unsafe fn setup(build: &mut Build) { - // Enable the Windows Error Reporting dialog which msys disables, - // so we can JIT debug rustc - let mode = SetErrorMode(THREAD_ERROR_MODE::default()); - let mode = THREAD_ERROR_MODE(mode); - SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); - - // Create a new job object for us to use - let job = CreateJobObjectW(None, PCWSTR::null()).unwrap(); - - // Indicate that when all handles to the job object are gone that all - // process in the object should be killed. Note that this includes our - // entire process tree by default because we've added ourselves and our - // children will reside in the job by default. - let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default(); - info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if build.config.low_priority { - info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS; - info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0; - } - let r = SetInformationJobObject( - job, - JobObjectExtendedLimitInformation, - &info as *const _ as *const c_void, - mem::size_of_val(&info) as u32, - ) - .ok(); - assert!(r.is_ok(), "{}", io::Error::last_os_error()); - - // Assign our process to this job object. Note that if this fails, one very - // likely reason is that we are ourselves already in a job object! This can - // happen on the build bots that we've got for Windows, or if just anyone - // else is instrumenting the build. In this case we just bail out - // immediately and assume that they take care of it. - // - // Also note that nested jobs (why this might fail) are supported in recent - // versions of Windows, but the version of Windows that our bots are running - // at least don't support nested job objects. - let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok(); - if r.is_err() { - CloseHandle(job); - return; - } - - // If we've got a parent process (e.g., the python script that called us) - // then move ownership of this job object up to them. That way if the python - // script is killed (e.g., via ctrl-c) then we'll all be torn down. - // - // If we don't have a parent (e.g., this was run directly) then we - // intentionally leak the job object handle. When our process exits - // (normally or abnormally) it will close the handle implicitly, causing all - // processes in the job to be cleaned up. - let pid = match env::var("BOOTSTRAP_PARENT_ID") { - Ok(s) => s, - Err(..) => return, - }; - - let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { - Some(parent) => parent, - _ => { - // If we get a null parent pointer here, it is possible that either - // we have an invalid pid or the parent process has been closed. - // Since the first case rarely happens - // (only when wrongly setting the environmental variable), - // it might be better to improve the experience of the second case - // when users have interrupted the parent process and we haven't finish - // duplicating the handle yet. We just need close the job object if that occurs. - CloseHandle(job); - return; - } - }; - - let mut parent_handle = HANDLE::default(); - let r = DuplicateHandle( - GetCurrentProcess(), - job, - parent, - &mut parent_handle, - 0, - false, - DUPLICATE_SAME_ACCESS, - ) - .ok(); - - // If this failed, well at least we tried! An example of DuplicateHandle - // failing in the past has been when the wrong python2 package spawned this - // build system (e.g., the `python2` package in MSYS instead of - // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure - // mode" here is that we only clean everything up when the build system - // dies, not when the python parent does, so not too bad. - if r.is_err() { - CloseHandle(job); - } -} diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/src/bin/main.rs similarity index 100% rename from src/bootstrap/bin/main.rs rename to src/bootstrap/src/bin/main.rs diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs similarity index 98% rename from src/bootstrap/bin/rustc.rs rename to src/bootstrap/src/bin/rustc.rs index 6cc5162120a9..241ae16e5953 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -15,19 +15,24 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. -include!("../dylib_util.rs"); -include!("./_helper.rs"); - use std::env; use std::path::PathBuf; -use std::process::{exit, Child, Command}; +use std::process::{Child, Command}; use std::time::Instant; +use dylib_util::{dylib_path, dylib_path_var}; + +#[path = "../utils/bin_helpers.rs"] +mod bin_helpers; + +#[path = "../utils/dylib.rs"] +mod dylib_util; + fn main() { let args = env::args_os().skip(1).collect::>(); let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); - let verbose = parse_rustc_verbose(); + let verbose = bin_helpers::parse_rustc_verbose(); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs similarity index 91% rename from src/bootstrap/bin/rustdoc.rs rename to src/bootstrap/src/bin/rustdoc.rs index 6561c1c1933c..f5f80ba2a0b8 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -5,17 +5,21 @@ use std::env; use std::ffi::OsString; use std::path::PathBuf; -use std::process::{exit, Command}; +use std::process::Command; -include!("../dylib_util.rs"); +use dylib_util::{dylib_path, dylib_path_var}; -include!("./_helper.rs"); +#[path = "../utils/bin_helpers.rs"] +mod bin_helpers; + +#[path = "../utils/dylib.rs"] +mod dylib_util; fn main() { let args = env::args_os().skip(1).collect::>(); - let stage = parse_rustc_stage(); - let verbose = parse_rustc_verbose(); + let stage = bin_helpers::parse_rustc_stage(); + let verbose = bin_helpers::parse_rustc_verbose(); let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set"); let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set"); diff --git a/src/bootstrap/bin/sccache-plus-cl.rs b/src/bootstrap/src/bin/sccache-plus-cl.rs similarity index 100% rename from src/bootstrap/bin/sccache-plus-cl.rs rename to src/bootstrap/src/bin/sccache-plus-cl.rs diff --git a/src/bootstrap/check.rs b/src/bootstrap/src/core/build_steps/check.rs similarity index 96% rename from src/bootstrap/check.rs rename to src/bootstrap/src/core/build_steps/check.rs index b417abc00f5b..121925b56a05 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -1,10 +1,12 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo}; -use crate::config::TargetSelection; -use crate::tool::{prepare_tool_cargo, SourceType}; +use crate::core::build_steps::compile::{ + add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, +}; +use crate::core::build_steps::tool::{prepare_tool_cargo, SourceType}; +use crate::core::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::cache::Interned; use crate::INTERNER; use crate::{Compiler, Mode, Subcommand}; use std::path::{Path, PathBuf}; @@ -16,7 +18,7 @@ pub struct Std { /// /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// - /// [`compile::Rustc`]: crate::compile::Rustc + /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc crates: Interned>, } @@ -193,7 +195,7 @@ pub struct Rustc { /// /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// - /// [`compile::Rustc`]: crate::compile::Rustc + /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc crates: Interned>, } @@ -237,8 +239,8 @@ impl Step for Rustc { // the sysroot for the compiler to find. Otherwise, we're going to // fail when building crates that need to generate code (e.g., build // scripts and their dependencies). - builder.ensure(crate::compile::Std::new(compiler, compiler.host)); - builder.ensure(crate::compile::Std::new(compiler, target)); + builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host)); + builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target)); } else { builder.ensure(Std::new(target)); } @@ -387,7 +389,7 @@ impl Step for RustAnalyzer { &["rust-analyzer/in-rust-tree".to_owned()], ); - cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES); + cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES); // For ./x.py clippy, don't check those targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs similarity index 98% rename from src/bootstrap/clean.rs rename to src/bootstrap/src/core/build_steps/clean.rs index 7389816b44c7..679770ce0ec7 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -9,9 +9,9 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; -use crate::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::util::t; +use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; +use crate::utils::cache::Interned; +use crate::utils::helpers::t; use crate::{Build, Compiler, Mode, Subcommand}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs similarity index 98% rename from src/bootstrap/compile.rs rename to src/bootstrap/src/core/build_steps/compile.rs index 623fa5fa111a..441931e415cc 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -19,16 +19,17 @@ use std::str; use serde_derive::Deserialize; -use crate::builder::crate_description; -use crate::builder::Cargo; -use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; -use crate::cache::{Interned, INTERNER}; -use crate::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; -use crate::dist; -use crate::llvm; -use crate::tool::SourceType; -use crate::util::get_clang_cl_resource_dir; -use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date}; +use crate::core::build_steps::dist; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::SourceType; +use crate::core::builder::crate_description; +use crate::core::builder::Cargo; +use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; +use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, +}; use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; use filetime::FileTime; @@ -510,7 +511,7 @@ impl Step for StdLink { let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() { // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too let lib = builder.sysroot_libdir_relative(self.compiler); - let sysroot = builder.ensure(crate::compile::Sysroot { + let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot { compiler: self.compiler, force_recompile: self.force_recompile, }); @@ -1016,7 +1017,8 @@ pub fn rustc_cargo_env( // detected that LLVM is already built and good to go which helps prevent // busting caches (e.g. like #71152). if builder.config.llvm_enabled() { - let building_is_expensive = crate::llvm::prebuilt_llvm_config(builder, target).is_err(); + let building_is_expensive = + crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target).is_err(); // `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage; let should_skip_build = building_is_expensive && can_skip_build; @@ -1684,7 +1686,7 @@ impl Step for Assemble { builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe)); let self_contained_lld_dir = libdir_bin.join("gcc-ld"); t!(fs::create_dir(&self_contained_lld_dir)); - let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper { + let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper { compiler: build_compiler, target: target_compiler.host, }); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs similarity index 98% rename from src/bootstrap/dist.rs rename to src/bootstrap/src/core/build_steps/dist.rs index 7bb59e5a611e..47f41ab288d5 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -19,16 +19,16 @@ use std::process::Command; use object::read::archive::ArchiveFile; use object::BinaryFormat; -use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::{Interned, INTERNER}; -use crate::channel; -use crate::compile; -use crate::config::TargetSelection; -use crate::doc::DocumentationFormat; -use crate::llvm; -use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; -use crate::tool::{self, Tool}; -use crate::util::{exe, is_dylib, output, t, timeit}; +use crate::core::build_steps::compile; +use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::{self, Tool}; +use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::channel; +use crate::utils::helpers::{exe, is_dylib, output, t, timeit}; +use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { @@ -104,7 +104,7 @@ impl Step for JsonDocs { /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - builder.ensure(crate::doc::Std::new( + builder.ensure(crate::core::build_steps::doc::Std::new( builder.top_stage, host, builder, @@ -488,7 +488,7 @@ impl Step for Rustc { let man_src = builder.src.join("src/doc/man"); let man_dst = image.join("share/man/man1"); - // don't use our `bootstrap::util::{copy, cp_r}`, because those try + // don't use our `bootstrap::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates for file_entry in builder.read_dir(&man_src) { let page_src = file_entry.path(); @@ -2060,7 +2060,7 @@ impl Step for LlvmTools { } } - builder.ensure(crate::llvm::Llvm { target }); + builder.ensure(crate::core::build_steps::llvm::Llvm { target }); let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple); tarball.set_overlay(OverlayKind::LLVM); @@ -2119,10 +2119,10 @@ impl Step for RustDev { let mut tarball = Tarball::new(builder, "rust-dev", &target.triple); tarball.set_overlay(OverlayKind::LLVM); - builder.ensure(crate::llvm::Llvm { target }); + builder.ensure(crate::core::build_steps::llvm::Llvm { target }); // We want to package `lld` to use it with `download-ci-llvm`. - builder.ensure(crate::llvm::Lld { target }); + builder.ensure(crate::core::build_steps::llvm::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); // If updating this list, you likely want to change diff --git a/src/bootstrap/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs similarity index 98% rename from src/bootstrap/doc.rs rename to src/bootstrap/src/core/build_steps/doc.rs index 505f06ed12d7..628a4ece8e90 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -10,13 +10,13 @@ use std::fs; use std::path::{Path, PathBuf}; -use crate::builder::crate_description; -use crate::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::{Interned, INTERNER}; -use crate::compile; -use crate::config::{Config, TargetSelection}; -use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; -use crate::util::{dir_is_empty, symlink_dir, t, up_to_date}; +use crate::core::build_steps::compile; +use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool}; +use crate::core::builder::crate_description; +use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; macro_rules! submodule_helper { diff --git a/src/bootstrap/format.rs b/src/bootstrap/src/core/build_steps/format.rs similarity index 99% rename from src/bootstrap/format.rs rename to src/bootstrap/src/core/build_steps/format.rs index 11f2762f7666..0e260e69c85a 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. -use crate::builder::Builder; -use crate::util::{output, program_out_of_date, t}; +use crate::core::builder::Builder; +use crate::utils::helpers::{output, program_out_of_date, t}; use build_helper::ci::CiEnv; use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; diff --git a/src/bootstrap/install.rs b/src/bootstrap/src/core/build_steps/install.rs similarity index 98% rename from src/bootstrap/install.rs rename to src/bootstrap/src/core/build_steps/install.rs index 885b3a782367..391995b7c3b8 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -8,15 +8,13 @@ use std::fs; use std::path::{Component, Path, PathBuf}; use std::process::Command; -use crate::util::t; - -use crate::dist; -use crate::tarball::GeneratedTarball; +use crate::core::build_steps::dist; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::helpers::t; +use crate::utils::tarball::GeneratedTarball; use crate::{Compiler, Kind}; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::config::{Config, TargetSelection}; - #[cfg(target_os = "illumos")] const SHELL: &str = "bash"; #[cfg(not(target_os = "illumos"))] diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs similarity index 98% rename from src/bootstrap/llvm.rs rename to src/bootstrap/src/core/build_steps/llvm.rs index 4556831589bd..24351118a5aa 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -16,11 +16,10 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::Command; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::channel; -use crate::config::{Config, TargetSelection}; -use crate::util::get_clang_cl_resource_dir; -use crate::util::{self, exe, output, t, up_to_date}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::{Config, TargetSelection}; +use crate::utils::channel; +use crate::utils::helpers::{self, exe, get_clang_cl_resource_dir, output, t, up_to_date}; use crate::{CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; @@ -281,7 +280,7 @@ impl Step for Llvm { let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target); t!(stamp.remove()); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); t!(fs::create_dir_all(&out_dir)); // https://llvm.org/docs/CMake.html @@ -410,7 +409,7 @@ impl Step for Llvm { let mut enabled_llvm_projects = Vec::new(); - if util::forcing_clang_based_tests() { + if helpers::forcing_clang_based_tests() { enabled_llvm_projects.push("clang"); enabled_llvm_projects.push("compiler-rt"); } @@ -528,8 +527,12 @@ impl Step for Llvm { // If the shared library exists in LLVM's `/build/lib/` or `/lib/` folders, strip its // debuginfo. - crate::compile::strip_debug(builder, target, &out_dir.join("lib").join(&lib_name)); - crate::compile::strip_debug( + crate::core::build_steps::compile::strip_debug( + builder, + target, + &out_dir.join("lib").join(&lib_name), + ); + crate::core::build_steps::compile::strip_debug( builder, target, &out_dir.join("build").join("lib").join(&lib_name), @@ -846,7 +849,7 @@ impl Step for Lld { } let _guard = builder.msg_unstaged(Kind::Build, "LLD", target); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld")); @@ -877,7 +880,7 @@ impl Step for Lld { // `LD_LIBRARY_PATH` overrides) // if builder.config.rpath_enabled(target) - && util::use_host_linker(target) + && helpers::use_host_linker(target) && builder.config.llvm_link_shared() && target.contains("linux") { @@ -970,7 +973,7 @@ impl Step for Sanitizers { let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target); t!(stamp.remove()); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut cfg = cmake::Config::new(&compiler_rt_dir); cfg.profile("Release"); diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs new file mode 100644 index 000000000000..50d83789be82 --- /dev/null +++ b/src/bootstrap/src/core/build_steps/mod.rs @@ -0,0 +1,15 @@ +pub(crate) mod check; +pub(crate) mod clean; +pub(crate) mod compile; +pub(crate) mod dist; +pub(crate) mod doc; +pub(crate) mod format; +pub(crate) mod install; +pub(crate) mod llvm; +pub(crate) mod run; +pub(crate) mod setup; +pub(crate) mod suggest; +pub(crate) mod synthetic_targets; +pub(crate) mod test; +pub(crate) mod tool; +pub(crate) mod toolstate; diff --git a/src/bootstrap/run.rs b/src/bootstrap/src/core/build_steps/run.rs similarity index 96% rename from src/bootstrap/run.rs rename to src/bootstrap/src/core/build_steps/run.rs index f253f5225a10..d1d6b7e869ec 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -1,13 +1,13 @@ use std::path::PathBuf; use std::process::Command; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::config::TargetSelection; -use crate::dist::distdir; -use crate::flags::get_completion; -use crate::test; -use crate::tool::{self, SourceType, Tool}; -use crate::util::output; +use crate::core::build_steps::dist::distdir; +use crate::core::build_steps::test; +use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::flags::get_completion; +use crate::core::config::TargetSelection; +use crate::utils::helpers::output; use crate::Mode; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs similarity index 98% rename from src/bootstrap/setup.rs rename to src/bootstrap/src/core/build_steps/setup.rs index 14ec33147fb9..435ebb6df90d 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -1,4 +1,4 @@ -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::Config; use crate::{t, CONFIG_CHANGE_HISTORY}; use sha2::Digest; @@ -12,6 +12,7 @@ use std::str::FromStr; use std::{fmt, fs, io}; #[cfg(test)] +#[path = "../../tests/setup.rs"] mod tests; #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] @@ -35,7 +36,7 @@ static SETTINGS_HASHES: &[&str] = &[ "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", ]; -static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json"); +static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); impl Profile { fn include_path(&self, src_path: &Path) -> PathBuf { @@ -182,7 +183,7 @@ pub fn setup(config: &Config, profile: Profile) { eprintln!(); eprintln!( "note: the `tools` profile sets up the `stage2` toolchain (use \ - `rustup toolchain link 'name' host/build/stage2` to use rustc)" + `rustup toolchain link 'name' build/host/stage2` to use rustc)" ) } diff --git a/src/bootstrap/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs similarity index 93% rename from src/bootstrap/suggest.rs rename to src/bootstrap/src/core/build_steps/suggest.rs index f225104bda92..82fb10cebe07 100644 --- a/src/bootstrap/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -1,12 +1,11 @@ #![cfg_attr(feature = "build-metrics", allow(unused))] +use clap::Parser; +use std::path::PathBuf; use std::str::FromStr; -use std::path::PathBuf; - -use clap::Parser; - -use crate::{builder::Builder, tool::Tool}; +use crate::core::build_steps::tool::Tool; +use crate::core::builder::Builder; /// Suggests a list of possible `x.py` commands to run based on modified files in branch. pub fn suggest(builder: &Builder<'_>, run: bool) { @@ -62,7 +61,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { for sug in suggestions { let mut build: crate::Build = builder.build.clone(); build.config.paths = sug.2; - build.config.cmd = crate::flags::Flags::parse_from(["x.py", sug.0]).cmd; + build.config.cmd = crate::core::config::flags::Flags::parse_from(["x.py", sug.0]).cmd; if let Some(stage) = sug.1 { build.config.stage = stage; } diff --git a/src/bootstrap/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs similarity index 95% rename from src/bootstrap/synthetic_targets.rs rename to src/bootstrap/src/core/build_steps/synthetic_targets.rs index 7eeac9025c9b..d2c65b740dad 100644 --- a/src/bootstrap/synthetic_targets.rs +++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs @@ -7,8 +7,8 @@ //! one of the target specs already defined in this module, or create new ones by adding a new step //! that calls create_synthetic_target. -use crate::builder::{Builder, ShouldRun, Step}; -use crate::config::TargetSelection; +use crate::core::builder::{Builder, ShouldRun, Step}; +use crate::core::config::TargetSelection; use crate::Compiler; use std::process::{Command, Stdio}; @@ -76,7 +76,7 @@ fn create_synthetic_target( std::fs::write(&path, &serde_json::to_vec_pretty(&spec).unwrap()).unwrap(); let target = TargetSelection::create_synthetic(&name, path.to_str().unwrap()); - crate::cc_detect::find_target(builder, target); + crate::utils::cc_detect::find_target(builder, target); target } diff --git a/src/bootstrap/test.rs b/src/bootstrap/src/core/build_steps/test.rs similarity index 97% rename from src/bootstrap/test.rs rename to src/bootstrap/src/core/build_steps/test.rs index fb8ec0355c24..831a86940fb4 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -13,21 +13,24 @@ use std::process::{Command, Stdio}; use clap_complete::shells; -use crate::builder::crate_description; -use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::cache::INTERNER; -use crate::compile; -use crate::config::TargetSelection; -use crate::dist; -use crate::doc::DocumentationFormat; -use crate::flags::Subcommand; -use crate::llvm; -use crate::render_tests::add_flags_and_try_run_tests; -use crate::synthetic_targets::MirOptPanicAbortSyntheticTarget; -use crate::tool::{self, SourceType, Tool}; -use crate::toolstate::ToolState; -use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date}; +use crate::core::build_steps::compile; +use crate::core::build_steps::dist; +use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::llvm; +use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; +use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::build_steps::toolstate::ToolState; +use crate::core::builder::crate_description; +use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::core::config::flags::get_completion; +use crate::core::config::flags::Subcommand; +use crate::core::config::TargetSelection; +use crate::utils; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date, +}; +use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; @@ -167,7 +170,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" // Run the linkchecker. let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run_delaying_failure(linkchecker.arg(builder.out.join(host.triple).join("doc"))); } @@ -219,7 +222,11 @@ impl Step for HtmlCheck { } // Ensure that a few different kinds of documentation are available. builder.default_doc(&[]); - builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder)); + builder.ensure(crate::core::build_steps::doc::Rustc::new( + builder.top_stage, + self.target, + builder, + )); builder.run_delaying_failure( builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), @@ -260,7 +267,7 @@ impl Step for Cargotest { let out_dir = builder.out.join("ct"); t!(fs::create_dir_all(&out_dir)); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut cmd = builder.tool_cmd(Tool::CargoTest); builder.run_delaying_failure( cmd.arg(&cargo) @@ -328,7 +335,7 @@ impl Step for Cargo { builder, ); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); add_flags_and_try_run_tests(builder, &mut cargo); } } @@ -642,7 +649,7 @@ impl Step for Miri { // does not understand the flags added by `add_flags_and_try_run_test`. let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } @@ -658,7 +665,7 @@ impl Step for Miri { let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } } @@ -698,7 +705,7 @@ impl Step for Miri { let mut cargo = Command::from(cargo); { - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run(&mut cargo); } } @@ -859,7 +866,7 @@ impl Step for RustdocTheme { if builder.is_fuse_ld_lld(self.compiler.host) { cmd.env( "RUSTDOC_LLD_NO_THREADS", - util::lld_flag_no_threads(self.compiler.host.contains("windows")), + helpers::lld_flag_no_threads(self.compiler.host.contains("windows")), ); } builder.run_delaying_failure(&mut cmd); @@ -900,7 +907,8 @@ impl Step for RustdocJSStd { .arg("--test-folder") .arg(builder.src.join("tests/rustdoc-js-std")); for path in &builder.paths { - if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) { + if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) + { if !p.ends_with(".js") { eprintln!("A non-js file was given: `{}`", path.display()); panic!("Cannot run rustdoc-js-std tests"); @@ -908,7 +916,7 @@ impl Step for RustdocJSStd { command.arg("--test-file").arg(path); } } - builder.ensure(crate::doc::Std::new( + builder.ensure(crate::core::build_steps::doc::Std::new( builder.top_stage, self.target, builder, @@ -1035,7 +1043,7 @@ impl Step for RustdocGUI { .env("RUSTC", builder.rustc(self.compiler)); for path in &builder.paths { - if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { + if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { if !p.ends_with(".goml") { eprintln!("A non-goml file was given: `{}`", path.display()); panic!("Cannot run rustdoc-gui tests"); @@ -1058,7 +1066,7 @@ impl Step for RustdocGUI { cmd.arg("--npm").arg(npm); } - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let _guard = builder.msg_sysroot_tool( Kind::Test, self.compiler.stage, @@ -1066,7 +1074,7 @@ impl Step for RustdocGUI { self.compiler.host, self.target, ); - crate::render_tests::try_run_tests(builder, &mut cmd, true); + try_run_tests(builder, &mut cmd, true); } } @@ -1126,7 +1134,7 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to ); crate::exit!(1); } - crate::format::format(&builder, !builder.config.cmd.bless(), &[]); + crate::core::build_steps::format::format(&builder, !builder.config.cmd.bless(), &[]); } builder.info("tidy check"); @@ -1138,10 +1146,10 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] .map(|filename| builder.src.join("src/etc/completions").join(filename)); if builder.config.cmd.bless() { - builder.ensure(crate::run::GenerateCompletions); - } else if crate::flags::get_completion(shells::Bash, &bash).is_some() - || crate::flags::get_completion(shells::Fish, &fish).is_some() - || crate::flags::get_completion(shells::PowerShell, &powershell).is_some() + builder.ensure(crate::core::build_steps::run::GenerateCompletions); + } else if get_completion(shells::Bash, &bash).is_some() + || get_completion(shells::Fish, &fish).is_some() + || get_completion(shells::PowerShell, &powershell).is_some() || crate::flags::get_completion(shells::Zsh, &zsh).is_some() { eprintln!( @@ -1403,10 +1411,10 @@ impl Step for MirOpt { // have been detected by bootstrap if the target we're testing wasn't in the // --target flags. if !builder.cc.borrow().contains_key(&target_32bit) { - crate::cc_detect::find_target(builder, target_32bit); + utils::cc_detect::find_target(builder, target_32bit); } if !builder.cc.borrow().contains_key(&target_64bit) { - crate::cc_detect::find_target(builder, target_64bit); + utils::cc_detect::find_target(builder, target_64bit); } vec![target_32bit, target_64bit] @@ -1679,7 +1687,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the } } - if util::forcing_clang_based_tests() { + if helpers::forcing_clang_based_tests() { let clang_exe = builder.llvm_out(target).join("bin").join("clang"); cmd.arg("--run-clang-based-tests-with").arg(clang_exe); } @@ -1698,7 +1706,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the // Get test-args by striping suite path let mut test_args: Vec<&str> = paths .iter() - .filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder)) + .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder)) .collect(); test_args.append(&mut builder.config.test_args()); @@ -1887,7 +1895,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the compiler.host, target, ); - crate::render_tests::try_run_tests(builder, &mut cmd, false); + try_run_tests(builder, &mut cmd, false); if let Some(compare_mode) = compare_mode { cmd.arg("--compare-mode").arg(compare_mode); @@ -1909,8 +1917,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the "Check compiletest suite={} mode={} compare_mode={} ({} -> {})", suite, mode, compare_mode, &compiler.host, target )); - let _time = util::timeit(&builder); - crate::render_tests::try_run_tests(builder, &mut cmd, false); + let _time = helpers::timeit(&builder); + try_run_tests(builder, &mut cmd, false); } } } @@ -1981,7 +1989,7 @@ impl BookTest { compiler.host, compiler.host, ); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let toolstate = if builder.run_delaying_failure(&mut rustbook_cmd) { ToolState::TestPass } else { @@ -2003,7 +2011,7 @@ impl BookTest { // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` let mut stack = vec![builder.src.join(self.path)]; - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let mut files = Vec::new(); while let Some(p) = stack.pop() { if p.is_dir() { @@ -2114,7 +2122,7 @@ impl Step for ErrorIndex { let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); builder.run_quiet(&mut tool); drop(guard); // The tests themselves need to link to std, so make sure it is @@ -2236,7 +2244,7 @@ fn run_cargo_test<'a>( ) -> bool { let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); let _group = description.into().and_then(|what| { builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) }); @@ -2631,7 +2639,7 @@ impl Step for RemoteCopyLibs { for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); - if util::is_dylib(&name) { + if helpers::is_dylib(&name) { builder.run(Command::new(&tool).arg("push").arg(f.path())); } } @@ -2676,7 +2684,9 @@ impl Step for Distcheck { .current_dir(&dir), ); builder.run( - Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir), + Command::new(helpers::make(&builder.config.build.triple)) + .arg("check") + .current_dir(&dir), ); // Now make sure that rust-src has all of libstd's dependencies @@ -2833,7 +2843,7 @@ impl Step for LintDocs { /// Tests that the lint examples in the rustc book generate the correct /// lints and have the expected format. fn run(self, builder: &Builder<'_>) { - builder.ensure(crate::doc::RustcBook { + builder.ensure(crate::core::build_steps::doc::RustcBook { compiler: self.compiler, target: self.target, validate: true, @@ -3052,7 +3062,7 @@ impl Step for CodegenCranelift { &compiler.host, target )); - let _time = util::timeit(&builder); + let _time = helpers::timeit(&builder); // FIXME handle vendoring for source tarballs before removing the --skip-test below let download_dir = builder.out.join("cg_clif_download"); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs similarity index 99% rename from src/bootstrap/tool.rs rename to src/bootstrap/src/core/build_steps/tool.rs index f094dd9d7c90..5702fa62d7cc 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -3,12 +3,12 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; -use crate::channel::GitInfo; -use crate::compile; -use crate::config::TargetSelection; -use crate::toolstate::ToolState; -use crate::util::{add_dylib_path, exe, t}; +use crate::core::build_steps::compile; +use crate::core::build_steps::toolstate::ToolState; +use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::channel::GitInfo; +use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; use crate::{gha, Kind}; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs similarity index 99% rename from src/bootstrap/toolstate.rs rename to src/bootstrap/src/core/build_steps/toolstate.rs index 308023537d58..f892577ccbf7 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -1,5 +1,5 @@ -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::util::t; +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::utils::helpers::t; use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; use std::env; diff --git a/src/bootstrap/builder.rs b/src/bootstrap/src/core/builder.rs similarity index 99% rename from src/bootstrap/builder.rs rename to src/bootstrap/src/core/builder.rs index c714b09ec3ce..039a87e760d7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -12,20 +12,15 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; -use crate::cache::{Cache, Interned, INTERNER}; -use crate::config::{DryRun, SplitDebuginfo, TargetSelection}; -use crate::doc; -use crate::flags::{Color, Subcommand}; -use crate::install; -use crate::llvm; -use crate::run; -use crate::setup; -use crate::test; -use crate::tool::{self, SourceType}; -use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; +use crate::core::build_steps::llvm; +use crate::core::build_steps::tool::{self, SourceType}; +use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test}; +use crate::core::config::flags::{Color, Subcommand}; +use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; +use crate::utils::cache::{Cache, Interned, INTERNER}; +use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; +use crate::Crate; use crate::EXTRA_CHECK_CFGS; -use crate::{check, compile, Crate}; -use crate::{clean, dist}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; @@ -36,6 +31,10 @@ pub use crate::Compiler; use clap::ValueEnum; use once_cell::sync::{Lazy, OnceCell}; +#[cfg(test)] +#[path = "../tests/builder.rs"] +mod tests; + pub struct Builder<'a> { pub build: &'a Build, pub top_stage: u32, @@ -723,7 +722,7 @@ impl<'a> Builder<'a> { check::Bootstrap ), Kind::Test => describe!( - crate::toolstate::ToolStateCheck, + crate::core::build_steps::toolstate::ToolStateCheck, test::ExpandYamlAnchors, test::Tidy, test::Ui, @@ -1297,8 +1296,8 @@ impl<'a> Builder<'a> { // See comment in rustc_llvm/build.rs for why this is necessary, largely llvm-config // needs to not accidentally link to libLLVM in stage0/lib. - cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var()); - if let Some(e) = env::var_os(util::dylib_path_var()) { + cargo.env("REAL_LIBRARY_PATH_VAR", &helpers::dylib_path_var()); + if let Some(e) = env::var_os(helpers::dylib_path_var()) { cargo.env("REAL_LIBRARY_PATH", e); } @@ -1311,7 +1310,7 @@ impl<'a> Builder<'a> { // rustc_llvm. But if LLVM is stale, that'll be a tiny amount // of work comparatively, and we'd likely need to rebuild it anyway, // so that's okay. - if crate::llvm::prebuilt_llvm_config(self, target).is_err() { + if crate::core::build_steps::llvm::prebuilt_llvm_config(self, target).is_err() { cargo.env("RUST_CHECK", "1"); } } @@ -1643,7 +1642,7 @@ impl<'a> Builder<'a> { // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it // fun to pass a flag to a tool to pass a flag to pass a flag to a tool // to change a flag in a binary? - if self.config.rpath_enabled(target) && util::use_host_linker(target) { + if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); let rpath = if target.contains("apple") { // Note that we need to take one extra step on macOS to also pass @@ -2197,9 +2196,6 @@ impl<'a> Builder<'a> { } } -#[cfg(test)] -mod tests; - /// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler later. /// /// `-Z crate-attr` flags will be applied recursively on the target code using the `rustc_parse::parser::Parser`. diff --git a/src/bootstrap/config.rs b/src/bootstrap/src/core/config/config.rs similarity index 98% rename from src/bootstrap/config.rs rename to src/bootstrap/src/core/config/config.rs index 759d874a089a..7ca1bbad9684 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -4,6 +4,7 @@ //! how the build runs. #[cfg(test)] +#[path = "../../tests/config.rs"] mod tests; use std::cell::{Cell, RefCell}; @@ -17,19 +18,20 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; -use crate::cache::{Interned, INTERNER}; -use crate::cc_detect::{ndk_compiler, Language}; -use crate::channel::{self, GitInfo}; -use crate::compile::CODEGEN_BACKEND_PREFIX; -pub use crate::flags::Subcommand; -use crate::flags::{Color, Flags, Warnings}; -use crate::util::{exe, output, t}; +use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; +use crate::core::config::flags::{Color, Flags, Warnings}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::cc_detect::{ndk_compiler, Language}; +use crate::utils::channel::{self, GitInfo}; +use crate::utils::helpers::{exe, output, t}; use build_helper::exit; use once_cell::sync::OnceCell; use semver::Version; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; +pub use crate::core::config::flags::Subcommand; + macro_rules! check_ci_llvm { ($name:expr) => { assert!( @@ -547,7 +549,7 @@ impl Target { /// `Config` structure. #[derive(Deserialize, Default)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct TomlConfig { +pub(crate) struct TomlConfig { changelog_seen: Option, // FIXME: Deprecated field. Remove it at 2024. change_id: Option, build: Option, @@ -1269,7 +1271,7 @@ impl Config { // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. if !config.out.is_absolute() { // `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead. - config.out = crate::util::absolute(&config.out); + config.out = crate::utils::helpers::absolute(&config.out); } config.initial_rustc = if let Some(rustc) = build.rustc { @@ -1527,11 +1529,12 @@ impl Config { config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm"); - crate::llvm::is_ci_llvm_available(&config, asserts) + crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) } Some(StringOrBool::Bool(b)) => b, None => { - config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, asserts) + config.channel == "dev" + && crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) } }; @@ -1573,8 +1576,8 @@ impl Config { config.llvm_link_shared.set(Some(true)); } } else { - config.llvm_from_ci = - config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, false); + config.llvm_from_ci = config.channel == "dev" + && crate::core::build_steps::llvm::is_ci_llvm_available(&config, false); } if let Some(t) = toml.target { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/src/core/config/flags.rs similarity index 99% rename from src/bootstrap/flags.rs rename to src/bootstrap/src/core/config/flags.rs index 5a6a5f37fc6f..dea553035449 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -7,9 +7,9 @@ use std::path::{Path, PathBuf}; use clap::{CommandFactory, Parser, ValueEnum}; -use crate::builder::{Builder, Kind}; -use crate::config::{target_selection_list, Config, TargetSelectionList}; -use crate::setup::Profile; +use crate::core::build_steps::setup::Profile; +use crate::core::builder::{Builder, Kind}; +use crate::core::config::{target_selection_list, Config, TargetSelectionList}; use crate::{Build, DocTests}; #[derive(Copy, Clone, Default, Debug, ValueEnum)] diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs new file mode 100644 index 000000000000..9c6861826d60 --- /dev/null +++ b/src/bootstrap/src/core/config/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod config; +pub(crate) mod flags; + +pub use config::*; diff --git a/src/bootstrap/download.rs b/src/bootstrap/src/core/download.rs similarity index 99% rename from src/bootstrap/download.rs rename to src/bootstrap/src/core/download.rs index 2a0dec755996..5541a2f3e35e 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -11,13 +11,10 @@ use build_helper::ci::CiEnv; use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; -use crate::{ - config::RustfmtMetadata, - llvm::detect_llvm_sha, - t, - util::{check_run, exe, program_out_of_date}, - Config, -}; +use crate::core::build_steps::llvm::detect_llvm_sha; +use crate::core::config::RustfmtMetadata; +use crate::utils::helpers::{check_run, exe, program_out_of_date}; +use crate::{t, Config}; static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell = OnceCell::new(); diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/src/core/metadata.rs similarity index 98% rename from src/bootstrap/metadata.rs rename to src/bootstrap/src/core/metadata.rs index 3b20ceac8759..5802082326a8 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -3,8 +3,8 @@ use std::process::Command; use serde_derive::Deserialize; -use crate::cache::INTERNER; -use crate::util::output; +use crate::utils::cache::INTERNER; +use crate::utils::helpers::output; use crate::{t, Build, Crate}; /// For more information, see the output of diff --git a/src/bootstrap/src/core/mod.rs b/src/bootstrap/src/core/mod.rs new file mode 100644 index 000000000000..9e18d6704d4f --- /dev/null +++ b/src/bootstrap/src/core/mod.rs @@ -0,0 +1,6 @@ +pub(crate) mod build_steps; +pub(crate) mod builder; +pub(crate) mod config; +pub(crate) mod download; +pub(crate) mod metadata; +pub(crate) mod sanity; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/src/core/sanity.rs similarity index 98% rename from src/bootstrap/sanity.rs rename to src/bootstrap/src/core/sanity.rs index 0febdf250d3f..eec3be66a128 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,9 +15,9 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use crate::cache::INTERNER; -use crate::config::Target; -use crate::util::output; +use crate::core::config::Target; +use crate::utils::cache::INTERNER; +use crate::utils::helpers::output; use crate::Build; pub struct Finder { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/src/lib.rs similarity index 95% rename from src/bootstrap/lib.rs rename to src/bootstrap/src/lib.rs index a9a81cb25f6f..97c743074af4 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -28,70 +28,28 @@ use std::str; use build_helper::ci::{gha, CiEnv}; use build_helper::exit; -use channel::GitInfo; -use config::{DryRun, Target}; use filetime::FileTime; use once_cell::sync::OnceCell; +use termcolor::{ColorChoice, StandardStream, WriteColor}; +use utils::channel::GitInfo; -use crate::builder::Kind; -use crate::config::{LlvmLibunwind, TargetSelection}; -use crate::util::{ - dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, +use crate::core::builder; +use crate::core::builder::Kind; +use crate::core::config::flags; +use crate::core::config::{DryRun, Target}; +use crate::core::config::{LlvmLibunwind, TargetSelection}; +use crate::utils::cache::{Interned, INTERNER}; +use crate::utils::helpers::{ + self, dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, + try_run_suppressed, }; -mod builder; -mod cache; -mod cc_detect; -mod channel; -mod check; -mod clean; -mod compile; -mod config; -mod dist; -mod doc; -mod download; -mod flags; -mod format; -mod install; -mod llvm; -mod metadata; -mod render_tests; -mod run; -mod sanity; -mod setup; -mod suggest; -mod synthetic_targets; -mod tarball; -mod test; -mod tool; -mod toolstate; -pub mod util; +mod core; +mod utils; -#[cfg(feature = "build-metrics")] -mod metrics; - -#[cfg(windows)] -mod job; - -#[cfg(all(unix, not(target_os = "haiku")))] -mod job { - pub unsafe fn setup(build: &mut crate::Build) { - if build.config.low_priority { - libc::setpriority(libc::PRIO_PGRP as _, 0, 10); - } - } -} - -#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))] -mod job { - pub unsafe fn setup(_build: &mut crate::Build) {} -} - -pub use crate::builder::PathSet; -use crate::cache::{Interned, INTERNER}; -pub use crate::config::Config; -pub use crate::flags::Subcommand; -use termcolor::{ColorChoice, StandardStream, WriteColor}; +pub use crate::core::builder::PathSet; +pub use crate::core::config::flags::Subcommand; +pub use crate::core::config::Config; const LLVM_TOOLS: &[&str] = &[ "llvm-cov", // used to generate coverage report @@ -210,12 +168,12 @@ pub struct Build { src: PathBuf, out: PathBuf, bootstrap_out: PathBuf, - cargo_info: channel::GitInfo, - rust_analyzer_info: channel::GitInfo, - clippy_info: channel::GitInfo, - miri_info: channel::GitInfo, - rustfmt_info: channel::GitInfo, - in_tree_llvm_info: channel::GitInfo, + cargo_info: GitInfo, + rust_analyzer_info: GitInfo, + clippy_info: GitInfo, + miri_info: GitInfo, + rustfmt_info: GitInfo, + in_tree_llvm_info: GitInfo, local_rebuild: bool, fail_fast: bool, doc_tests: DocTests, @@ -248,7 +206,7 @@ pub struct Build { prerelease_version: Cell>, #[cfg(feature = "build-metrics")] - metrics: metrics::BuildMetrics, + metrics: crate::utils::metrics::BuildMetrics, } #[derive(Debug, Clone)] @@ -372,16 +330,15 @@ impl Build { let is_sudo = false; let omit_git_hash = config.omit_git_hash; - let rust_info = channel::GitInfo::new(omit_git_hash, &src); - let cargo_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/cargo")); - let rust_analyzer_info = - channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer")); - let clippy_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); - let miri_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); - let rustfmt_info = channel::GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); + let rust_info = GitInfo::new(omit_git_hash, &src); + let cargo_info = GitInfo::new(omit_git_hash, &src.join("src/tools/cargo")); + let rust_analyzer_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer")); + let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); + let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); + let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); // we always try to use git for LLVM builds - let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project")); + let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project")); let initial_target_libdir_str = if config.dry_run() { "/dummy/lib/path/to/lib/".to_string() @@ -474,7 +431,7 @@ impl Build { prerelease_version: Cell::new(None), #[cfg(feature = "build-metrics")] - metrics: metrics::BuildMetrics::init(), + metrics: crate::utils::metrics::BuildMetrics::init(), }; // If local-rust is the same major.minor as the current version, then force a @@ -493,7 +450,7 @@ impl Build { } build.verbose("finding compilers"); - cc_detect::find(&build); + utils::cc_detect::find(&build); // When running `setup`, the profile is about to change, so any requirements we have now may // be different on the next invocation. Don't check for them until the next time x.py is // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. @@ -501,7 +458,7 @@ impl Build { // Similarly, for `setup` we don't actually need submodules or cargo metadata. if !matches!(build.config.cmd, Subcommand::Setup { .. }) { build.verbose("running sanity check"); - sanity::check(&mut build); + crate::core::sanity::check(&mut build); // Make sure we update these before gathering metadata so we don't get an error about missing // Cargo.toml files. @@ -513,7 +470,7 @@ impl Build { build.update_existing_submodules(); build.verbose("learning about cargo"); - metadata::build(&mut build); + crate::core::metadata::build(&mut build); } // Make a symbolic link so we can use a consistent directory in the documentation. @@ -549,7 +506,7 @@ impl Build { // NOTE: The check for the empty directory is here because when running x.py the first time, // the submodule won't be checked out. Check it out now so we can build it. - if !channel::GitInfo::new(false, &absolute_path).is_managed_git_subrepository() + if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() && !dir_is_empty(&absolute_path) { return; @@ -663,7 +620,7 @@ impl Build { // Sample output: `submodule.src/rust-installer.path src/tools/rust-installer` let submodule = Path::new(line.splitn(2, ' ').nth(1).unwrap()); // Don't update the submodule unless it's already been cloned. - if channel::GitInfo::new(false, submodule).is_managed_git_subrepository() { + if GitInfo::new(false, submodule).is_managed_git_subrepository() { self.update_submodule(submodule); } } @@ -672,7 +629,7 @@ impl Build { /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { - job::setup(self); + crate::utils::job::setup(self); } // Download rustfmt early so that it can be used in rust-analyzer configs. @@ -681,10 +638,14 @@ impl Build { // hardcoded subcommands match &self.config.cmd { Subcommand::Format { check } => { - return format::format(&builder::Builder::new(&self), *check, &self.config.paths); + return core::build_steps::format::format( + &builder::Builder::new(&self), + *check, + &self.config.paths, + ); } Subcommand::Suggest { run } => { - return suggest::suggest(&builder::Builder::new(&self), *run); + return core::build_steps::suggest::suggest(&builder::Builder::new(&self), *run); } _ => (), } @@ -1065,7 +1026,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. /// - /// [`Step`]: crate::builder::Step + /// [`Step`]: crate::core::builder::Step #[must_use = "Groups should not be dropped until the Step finishes running"] #[track_caller] fn msg( @@ -1093,7 +1054,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. /// - /// [`Step`]: crate::builder::Step + /// [`Step`]: crate::core::builder::Step #[must_use = "Groups should not be dropped until the Step finishes running"] #[track_caller] fn msg_unstaged( @@ -1253,7 +1214,7 @@ impl Build { // that are only existed in CXX libraries Some(self.cxx.borrow()[&target].path().into()) } else if target != self.config.build - && util::use_host_linker(target) + && helpers::use_host_linker(target) && !target.contains("msvc") { Some(self.cc(target)) @@ -1278,7 +1239,7 @@ impl Build { options[0] = Some("-Clink-arg=-fuse-ld=lld".to_string()); } - let no_threads = util::lld_flag_no_threads(target.contains("windows")); + let no_threads = helpers::lld_flag_no_threads(target.contains("windows")); options[1] = Some(format!("-Clink-arg=-Wl,{no_threads}")); } @@ -1418,7 +1379,7 @@ impl Build { fn extract_beta_rev_from_file>(version_file: P) -> Option { let version = fs::read_to_string(version_file).ok()?; - extract_beta_rev(&version) + helpers::extract_beta_rev(&version) } if let Some(s) = self.prerelease_version.get() { @@ -1732,7 +1693,7 @@ impl Build { /// Returns if config.ninja is enabled, and checks for ninja existence, /// exiting with a nicer error message if not. fn ninja(&self) -> bool { - let mut cmd_finder = crate::sanity::Finder::new(); + let mut cmd_finder = crate::core::sanity::Finder::new(); if self.config.ninja_in_file { // Some Linux distros rename `ninja` to `ninja-build`. @@ -1798,17 +1759,6 @@ to download LLVM rather than building it. } } -/// Extract the beta revision from the full version string. -/// -/// The full version string looks like "a.b.c-beta.y". And we need to extract -/// the "y" part from the string. -pub fn extract_beta_rev(version: &str) -> Option { - let parts = version.splitn(2, "-beta.").collect::>(); - let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string())); - - count -} - #[cfg(unix)] fn chmod(path: &Path, perms: u32) { use std::os::unix::fs::*; diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/src/tests/builder.rs similarity index 99% rename from src/bootstrap/builder/tests.rs rename to src/bootstrap/src/tests/builder.rs index 0294102286e9..96139f7b099c 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/src/tests/builder.rs @@ -1,6 +1,6 @@ use super::*; -use crate::config::{Config, DryRun, TargetSelection}; -use crate::doc::DocumentationFormat; +use crate::core::config::{Config, DryRun, TargetSelection}; +use crate::core::build_steps::doc::DocumentationFormat; use std::thread; fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { @@ -158,7 +158,7 @@ fn alias_and_path_for_library() { #[test] fn test_beta_rev_parsing() { - use crate::extract_beta_rev; + use crate::utils::helpers::extract_beta_rev; // single digit revision assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string())); @@ -174,7 +174,7 @@ fn test_beta_rev_parsing() { mod defaults { use super::{configure, first, run_build}; - use crate::builder::*; + use crate::core::builder::*; use crate::Config; use pretty_assertions::assert_eq; @@ -285,7 +285,7 @@ mod defaults { mod dist { use super::{first, run_build, Config}; - use crate::builder::*; + use crate::core::builder::*; use pretty_assertions::assert_eq; fn configure(host: &[&str], target: &[&str]) -> Config { diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/src/tests/config.rs similarity index 97% rename from src/bootstrap/config/tests.rs rename to src/bootstrap/src/tests/config.rs index ae8363b6de9c..59bd52a94dc8 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/src/tests/config.rs @@ -1,6 +1,6 @@ -use crate::config::TomlConfig; - +use crate::core::config::TomlConfig; use super::{Config, Flags}; + use clap::CommandFactory; use serde::Deserialize; use std::{ @@ -18,7 +18,7 @@ fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - if crate::llvm::is_ci_llvm_modified(&parse("")) { + if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); return; } @@ -137,7 +137,7 @@ build-config = {} assert_eq!(config.change_id, Some(1), "setting top-level value"); assert_eq!( config.rust_lto, - crate::config::RustcLto::Fat, + crate::core::config::RustcLto::Fat, "setting string value without quotes" ); assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes"); @@ -175,7 +175,7 @@ fn profile_user_dist() { "profile = \"user\"".to_owned() } else { assert!(file.ends_with("config.dist.toml")); - std::fs::read_to_string(dbg!(file)).unwrap() + std::fs::read_to_string(file).unwrap() }; toml::from_str(&contents) .and_then(|table: toml::Value| TomlConfig::deserialize(table)) diff --git a/src/bootstrap/setup/tests.rs b/src/bootstrap/src/tests/setup.rs similarity index 100% rename from src/bootstrap/setup/tests.rs rename to src/bootstrap/src/tests/setup.rs diff --git a/src/bootstrap/bin/_helper.rs b/src/bootstrap/src/utils/bin_helpers.rs similarity index 73% rename from src/bootstrap/bin/_helper.rs rename to src/bootstrap/src/utils/bin_helpers.rs index 46c574c5bf45..b9177c490ac2 100644 --- a/src/bootstrap/bin/_helper.rs +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -1,8 +1,12 @@ +//! This file is meant to be included directly from bootstrap shims to avoid a +//! dependency on the bootstrap library. This reduces the binary size and +//! improves compilation time by reducing the linking time. + /// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`. /// If it was not defined, returns 0 by default. /// /// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer. -fn parse_rustc_verbose() -> usize { +pub(crate) fn parse_rustc_verbose() -> usize { use std::str::FromStr; match std::env::var("RUSTC_VERBOSE") { @@ -15,11 +19,11 @@ fn parse_rustc_verbose() -> usize { /// /// If "RUSTC_STAGE" was not set, the program will be terminated with 101. #[allow(unused)] -fn parse_rustc_stage() -> String { +pub(crate) fn parse_rustc_stage() -> String { std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. eprintln!("rustc shim: fatal: RUSTC_STAGE was not set"); eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap"); - exit(101); + std::process::exit(101); }) } diff --git a/src/bootstrap/cache.rs b/src/bootstrap/src/utils/cache.rs similarity index 99% rename from src/bootstrap/cache.rs rename to src/bootstrap/src/utils/cache.rs index 53e4ff03431f..1b2aa9c234bb 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -14,7 +14,7 @@ use std::sync::Mutex; // FIXME: replace with std::lazy after it gets stabilized and reaches beta use once_cell::sync::Lazy; -use crate::builder::Step; +use crate::core::builder::Step; pub struct Interned(usize, PhantomData<*const T>); diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs similarity index 99% rename from src/bootstrap/cc_detect.rs rename to src/bootstrap/src/utils/cc_detect.rs index 2496c2a9db52..3d3f93f7720e 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -26,8 +26,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::{env, iter}; -use crate::config::{Target, TargetSelection}; -use crate::util::output; +use crate::core::config::{Target, TargetSelection}; +use crate::utils::helpers::output; use crate::{Build, CLang, GitRepo}; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, diff --git a/src/bootstrap/channel.rs b/src/bootstrap/src/utils/channel.rs similarity index 99% rename from src/bootstrap/channel.rs rename to src/bootstrap/src/utils/channel.rs index 87018574048a..e59d7f22aaae 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/src/utils/channel.rs @@ -9,8 +9,7 @@ use std::fs; use std::path::Path; use std::process::Command; -use crate::util::output; -use crate::util::t; +use crate::utils::helpers::{output, t}; use crate::Build; #[derive(Clone, Default)] diff --git a/src/bootstrap/dylib_util.rs b/src/bootstrap/src/utils/dylib.rs similarity index 62% rename from src/bootstrap/dylib_util.rs rename to src/bootstrap/src/utils/dylib.rs index b14c0bed66c2..279a6a010f1d 100644 --- a/src/bootstrap/dylib_util.rs +++ b/src/bootstrap/src/utils/dylib.rs @@ -1,7 +1,4 @@ -// Various utilities for working with dylib paths. -// -// This file is meant to be included directly to avoid a dependency on the bootstrap library from -// the rustc and rustdoc wrappers. This improves compilation time by reducing the linking time. +//! Various utilities for working with dylib paths. /// Returns the environment variable which the dynamic library lookup path /// resides in for this platform. @@ -21,10 +18,10 @@ pub fn dylib_path_var() -> &'static str { /// Parses the `dylib_path_var()` environment variable, returning a list of /// paths that are members of this lookup path. -pub fn dylib_path() -> Vec { - let var = match env::var_os(dylib_path_var()) { +pub fn dylib_path() -> Vec { + let var = match std::env::var_os(dylib_path_var()) { Some(v) => v, None => return vec![], }; - env::split_paths(&var).collect() + std::env::split_paths(&var).collect() } diff --git a/src/bootstrap/util.rs b/src/bootstrap/src/utils/helpers.rs similarity index 95% rename from src/bootstrap/util.rs rename to src/bootstrap/src/utils/helpers.rs index 3c4a21434c00..bb84b70d987f 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -12,10 +12,12 @@ use std::process::{Command, Stdio}; use std::str; use std::time::{Instant, SystemTime, UNIX_EPOCH}; -use crate::builder::Builder; -use crate::config::{Config, TargetSelection}; +use crate::core::builder::Builder; +use crate::core::config::{Config, TargetSelection}; use crate::OnceCell; +pub use crate::utils::dylib::{dylib_path, dylib_path_var}; + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The file/line of the panic @@ -81,8 +83,6 @@ pub fn add_dylib_path(path: Vec, cmd: &mut Command) { cmd.env(dylib_path_var(), t!(env::join_paths(list))); } -include!("dylib_util.rs"); - /// Adds a list of lookup paths to `cmd`'s link library lookup path. pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { let mut list = link_lib_path(); @@ -293,23 +293,6 @@ pub fn output(cmd: &mut Command) -> String { String::from_utf8(output.stdout).unwrap() } -pub fn output_result(cmd: &mut Command) -> Result { - let output = match cmd.stderr(Stdio::inherit()).output() { - Ok(status) => status, - Err(e) => return Err(format!("failed to run command: {cmd:?}: {e}")), - }; - if !output.status.success() { - return Err(format!( - "command did not execute successfully: {:?}\n\ - expected success, got: {}\n{}", - cmd, - output.status, - String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? - )); - } - Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?) -} - /// Returns the last-modified time for `path`, or zero if it doesn't exist. pub fn mtime(path: &Path) -> SystemTime { fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) @@ -495,3 +478,14 @@ pub fn lld_flag_no_threads(is_windows: bool) -> &'static str { pub fn dir_is_empty(dir: &Path) -> bool { t!(std::fs::read_dir(dir)).next().is_none() } + +/// Extract the beta revision from the full version string. +/// +/// The full version string looks like "a.b.c-beta.y". And we need to extract +/// the "y" part from the string. +pub fn extract_beta_rev(version: &str) -> Option { + let parts = version.splitn(2, "-beta.").collect::>(); + let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string())); + + count +} diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs new file mode 100644 index 000000000000..37235134a28c --- /dev/null +++ b/src/bootstrap/src/utils/job.rs @@ -0,0 +1,161 @@ +#[cfg(windows)] +pub use for_windows::*; + +#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))] +pub unsafe fn setup(_build: &mut crate::Build) {} + +#[cfg(all(unix, not(target_os = "haiku")))] +pub unsafe fn setup(build: &mut crate::Build) { + if build.config.low_priority { + libc::setpriority(libc::PRIO_PGRP as _, 0, 10); + } +} + +#[cfg(windows)] +mod for_windows { + //! Job management on Windows for bootstrapping + //! + //! Most of the time when you're running a build system (e.g., make) you expect + //! Ctrl-C or abnormal termination to actually terminate the entire tree of + //! process in play, not just the one at the top. This currently works "by + //! default" on Unix platforms because Ctrl-C actually sends a signal to the + //! *process group* rather than the parent process, so everything will get torn + //! down. On Windows, however, this does not happen and Ctrl-C just kills the + //! parent process. + //! + //! To achieve the same semantics on Windows we use Job Objects to ensure that + //! all processes die at the same time. Job objects have a mode of operation + //! where when all handles to the object are closed it causes all child + //! processes associated with the object to be terminated immediately. + //! Conveniently whenever a process in the job object spawns a new process the + //! child will be associated with the job object as well. This means if we add + //! ourselves to the job object we create then everything will get torn down! + //! + //! Unfortunately most of the time the build system is actually called from a + //! python wrapper (which manages things like building the build system) so this + //! all doesn't quite cut it so far. To go the last mile we duplicate the job + //! object handle into our parent process (a python process probably) and then + //! close our own handle. This means that the only handle to the job object + //! resides in the parent python process, so when python dies the whole build + //! system dies (as one would probably expect!). + //! + //! Note that this module has a #[cfg(windows)] above it as none of this logic + //! is required on Unix. + + use crate::Build; + use std::env; + use std::ffi::c_void; + use std::io; + use std::mem; + + use windows::{ + core::PCWSTR, + Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE}, + Win32::System::Diagnostics::Debug::{ + SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE, + }, + Win32::System::JobObjects::{ + AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation, + SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, + JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, + }, + Win32::System::Threading::{ + GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE, + }, + }; + + pub unsafe fn setup(build: &mut Build) { + // Enable the Windows Error Reporting dialog which msys disables, + // so we can JIT debug rustc + let mode = SetErrorMode(THREAD_ERROR_MODE::default()); + let mode = THREAD_ERROR_MODE(mode); + SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); + + // Create a new job object for us to use + let job = CreateJobObjectW(None, PCWSTR::null()).unwrap(); + + // Indicate that when all handles to the job object are gone that all + // process in the object should be killed. Note that this includes our + // entire process tree by default because we've added ourselves and our + // children will reside in the job by default. + let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default(); + info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if build.config.low_priority { + info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS; + info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0; + } + let r = SetInformationJobObject( + job, + JobObjectExtendedLimitInformation, + &info as *const _ as *const c_void, + mem::size_of_val(&info) as u32, + ) + .ok(); + assert!(r.is_ok(), "{}", io::Error::last_os_error()); + + // Assign our process to this job object. Note that if this fails, one very + // likely reason is that we are ourselves already in a job object! This can + // happen on the build bots that we've got for Windows, or if just anyone + // else is instrumenting the build. In this case we just bail out + // immediately and assume that they take care of it. + // + // Also note that nested jobs (why this might fail) are supported in recent + // versions of Windows, but the version of Windows that our bots are running + // at least don't support nested job objects. + let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok(); + if r.is_err() { + CloseHandle(job); + return; + } + + // If we've got a parent process (e.g., the python script that called us) + // then move ownership of this job object up to them. That way if the python + // script is killed (e.g., via ctrl-c) then we'll all be torn down. + // + // If we don't have a parent (e.g., this was run directly) then we + // intentionally leak the job object handle. When our process exits + // (normally or abnormally) it will close the handle implicitly, causing all + // processes in the job to be cleaned up. + let pid = match env::var("BOOTSTRAP_PARENT_ID") { + Ok(s) => s, + Err(..) => return, + }; + + let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { + Some(parent) => parent, + _ => { + // If we get a null parent pointer here, it is possible that either + // we have an invalid pid or the parent process has been closed. + // Since the first case rarely happens + // (only when wrongly setting the environmental variable), + // it might be better to improve the experience of the second case + // when users have interrupted the parent process and we haven't finish + // duplicating the handle yet. We just need close the job object if that occurs. + CloseHandle(job); + return; + } + }; + + let mut parent_handle = HANDLE::default(); + let r = DuplicateHandle( + GetCurrentProcess(), + job, + parent, + &mut parent_handle, + 0, + false, + DUPLICATE_SAME_ACCESS, + ) + .ok(); + + // If this failed, well at least we tried! An example of DuplicateHandle + // failing in the past has been when the wrong python2 package spawned this + // build system (e.g., the `python2` package in MSYS instead of + // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure + // mode" here is that we only clean everything up when the build system + // dies, not when the python parent does, so not too bad. + if r.is_err() { + CloseHandle(job); + } + } +} diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/src/utils/metrics.rs similarity index 99% rename from src/bootstrap/metrics.rs rename to src/bootstrap/src/utils/metrics.rs index cf8d33dfcb01..65794f05d2d9 100644 --- a/src/bootstrap/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -4,8 +4,8 @@ //! As this module requires additional dependencies not present during local builds, it's cfg'd //! away whenever the `build.metrics` config option is not set to `true`. -use crate::builder::{Builder, Step}; -use crate::util::t; +use crate::core::builder::{Builder, Step}; +use crate::utils::helpers::t; use crate::Build; use build_helper::metrics::{ JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs new file mode 100644 index 000000000000..7dcb6a828620 --- /dev/null +++ b/src/bootstrap/src/utils/mod.rs @@ -0,0 +1,14 @@ +//! This module contains integral components of the build and configuration process, providing +//! support for a wide range of tasks and operations such as caching, tarballs, release +//! channels, job management, etc. + +pub(crate) mod cache; +pub(crate) mod cc_detect; +pub(crate) mod channel; +pub(crate) mod dylib; +pub(crate) mod helpers; +pub(crate) mod job; +#[cfg(feature = "build-metrics")] +pub(crate) mod metrics; +pub(crate) mod render_tests; +pub(crate) mod tarball; diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs similarity index 99% rename from src/bootstrap/render_tests.rs rename to src/bootstrap/src/utils/render_tests.rs index 6802bf4511bc..f97aa9585135 100644 --- a/src/bootstrap/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -6,7 +6,7 @@ //! and rustc) libtest doesn't include the rendered human-readable output as a JSON field. We had //! to reimplement all the rendering logic in this module because of that. -use crate::builder::Builder; +use crate::core::builder::Builder; use std::io::{BufRead, BufReader, Read, Write}; use std::process::{ChildStdout, Command, Stdio}; use std::time::Duration; diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/src/utils/tarball.rs similarity index 95% rename from src/bootstrap/tarball.rs rename to src/bootstrap/src/utils/tarball.rs index 95d909c5730f..b437456f8a10 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -3,9 +3,10 @@ use std::{ process::Command, }; -use crate::builder::Builder; -use crate::channel; -use crate::util::t; +use crate::core::build_steps::dist::distdir; +use crate::core::builder::Builder; +use crate::utils::channel; +use crate::utils::helpers::t; #[derive(Copy, Clone)] pub(crate) enum OverlayKind { @@ -112,7 +113,7 @@ impl<'a> Tarball<'a> { } fn new_inner(builder: &'a Builder<'a>, component: &str, target: Option) -> Self { - let pkgname = crate::dist::pkgname(builder, component); + let pkgname = crate::core::build_steps::dist::pkgname(builder, component); let mut temp_dir = builder.out.join("tmp").join("tarball").join(component); if let Some(target) = &target { @@ -265,7 +266,7 @@ impl<'a> Tarball<'a> { t!(std::fs::rename(&self.image_dir, &dest)); self.run(|this, cmd| { - let distdir = crate::dist::distdir(this.builder); + let distdir = distdir(this.builder); t!(std::fs::create_dir_all(&distdir)); cmd.arg("tarball") .arg("--input") @@ -292,7 +293,7 @@ impl<'a> Tarball<'a> { .arg("--non-installed-overlay") .arg(&self.overlay_dir) .arg("--output-dir") - .arg(crate::dist::distdir(self.builder)); + .arg(distdir(self.builder)); } fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball { @@ -306,11 +307,11 @@ impl<'a> Tarball<'a> { self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644); } - let mut cmd = self.builder.tool_cmd(crate::tool::Tool::RustInstaller); + let mut cmd = self.builder.tool_cmd(crate::core::build_steps::tool::Tool::RustInstaller); let package_name = self.package_name(); self.builder.info(&format!("Dist {package_name}")); - let _time = crate::util::timeit(self.builder); + let _time = crate::utils::helpers::timeit(self.builder); build_cli(&self, &mut cmd); cmd.arg("--work-dir").arg(&self.temp_dir); @@ -344,7 +345,7 @@ impl<'a> Tarball<'a> { .unwrap_or("gz"); GeneratedTarball { - path: crate::dist::distdir(self.builder).join(format!("{package_name}.tar.{ext}")), + path: distdir(self.builder).join(format!("{package_name}.tar.{ext}")), decompressed_output, work: self.temp_dir, } diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 22aabda2bb34..99e3ce199f45 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -235,7 +235,7 @@ else args="$args --volume /tmp/toolstate:/tmp/toolstate" id=$(id -u) - if [[ "$id" != 0 && "$(docker -v)" =~ ^podman ]]; then + if [[ "$id" != 0 && "$(docker version)" =~ Podman ]]; then # Rootless podman creates a separate user namespace, where an inner # LOCAL_USER_ID will map to a different subuid range on the host. # The "keep-id" mode maps the current UID directly into the container. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 1fb5e56db5d7..db834600b9c1 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -244,7 +244,7 @@ target | std | host | notes `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) -[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) +[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7-A OpenHarmony | [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7-A Linux with uClibc, hardfloat diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md index 49eed366dacf..e1473bd966c4 100644 --- a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md +++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md @@ -2,15 +2,16 @@ **Tier: 3** -This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge. +This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. Rust support for this target is not affiliated with Sony, and is not derived from nor used with any official Sony SDK. ## Target maintainers -* [@amg98](https://github.com/amg98) * [@nikarh](https://github.com/nikarh) +* [@pheki](https://github.com/pheki) +* [@ZetaNumbers](https://github.com/ZetaNumbers) ## Requirements @@ -20,18 +21,16 @@ This target is cross-compiled, and requires installing [VITASDK](https://vitasdk `alloc`, and `panic_abort`. `std` is partially supported, but mostly works. Some APIs are unimplemented -and will simply return an error, such as `std::process`. An allocator is provided -by default. +and will simply return an error, such as `std::process`. -In order to support some APIs, binaries must be linked against `libc` written -for the target, using a linker for the target. These are provided by the -VITASDK toolchain. +This target generates binaries in the ELF format with thumb ISA by default. + +Binaries are linked with `arm-vita-eabi-gcc` provided by VITASDK toolchain. -This target generates binaries in the ELF format with thumb ISA. ## Building the target -Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build binaries with `std`: +Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build ELF binaries with `std`: ```sh cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf --release @@ -39,113 +38,45 @@ cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf - ## Building Rust programs -To test your developed rust programs on PlayStation Vita, first you must correctly package your elf. These steps can be preformed using tools available in VITASDK, and can be automated using a tool like `cargo-make`. +The recommended way to build artifacts that can be installed and run on PlayStation Vita is by using the [cargo-vita](https://github.com/vita-rust/cargo-vita) tool. This tool uses `build-std` and VITASDK toolchain to build artifacts runnable on Vita. -First, set up environment variables for `VITASDK`, and it's binaries: +To install the tool run: + +```sh +cargo install cargo-vita +``` + +[VITASDK](https://vitasdk.org/) toolchain must be installed, and the `VITASDK` environment variable must be set to its location, e.g.: ```sh export VITASDK=/opt/vitasdk -export PATH=$PATH:$VITASDK/bin ``` -Use the example below as a template for your project: +Add the following section to your project's `Cargo.toml`: + ```toml -[env] -TITLE = "Rust Hello World" -TITLEID = "RUST00001" - -# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...) -# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/ -STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys) -CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] } -CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release" - -[tasks.build] -description = "Build the project using `cargo`." -command = "cargo" -args = ["build", "-Z", "build-std=std,panic_abort", "--target=armv7-sony-vita-newlibeabihf", "--release"] - -[tasks.strip] -description = "Strip the produced ELF executable." -dependencies = ["build"] -command = "arm-vita-eabi-strip" -args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf'] - -[tasks.velf] -description = "Build an VELF executable from the obtained ELF file." -dependencies = ["strip"] -command = "vita-elf-create" -args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf'] - -[tasks.eboot-bin] -description = "Build an `eboot.bin` file from the obtained VELF file." -dependencies = ["velf"] -command = "vita-make-fself" -args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin'] - -[tasks.param-sfo] -description = "Build the `param.sfo` manifest using with given TITLE and TITLEID." -command = "vita-mksfoex" -args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo'] - -[tasks.manifest] -description = "List all static resources into a manifest file." -script = [ - 'mkdir -p "${CARGO_OUT_DIR}"', - ''' - if [ -d "${STATIC_DIR}" ]; then - find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST" - else - touch "${CARGO_OUT_DIR}/MANIFEST" - fi - ''' -] - -[tasks.vpk] -description = "Build a VPK distribution of the project executable and resources." -dependencies = ["eboot-bin", "param-sfo", "manifest"] -script_runner = "@rust" -script = [ - ''' - use std::io::BufRead; - use std::fs::File; - - fn main() { - - let crate_name = env!("CARGO_MAKE_CRATE_NAME"); - let static_dir = env!("STATIC_DIR"); - let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR")); - - let mut cmd = ::std::process::Command::new("vita-pack-vpk"); - cmd.arg("-s").arg(out_dir.join("param.sfo")); - cmd.arg("-b").arg(out_dir.join("eboot.bin")); - - // Add files from MANIFEST - if let Ok(file) = File::open(out_dir.join("MANIFEST")) { - let mut reader = ::std::io::BufReader::new(file); - let mut lines = reader.lines(); - while let Some(Ok(line)) = lines.next() { - let p1 = ::std::path::PathBuf::from(line); // path on FS - let p2 = p1.strip_prefix(static_dir).unwrap(); // path in VPK - cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display())); - } - } - - cmd.arg(out_dir.join(format!("{}.vpk", crate_name))) - .output() - .expect("command failed."); - } - ''' -] +[package.metadata.vita] +# A unique 9 character alphanumeric identifier of the app. +title_id = "RUSTAPP01" +# A title that will be used for the app. Optional, name will be used if not defined +title_name = "My application" ``` -After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, or you can use an [Vita3K](https://vita3k.org/) emulator. +To build a VPK with ELF in the release profile, run: + +```sh +cargo vita build vpk --release +``` + +After building a *.vpk file it can be uploaded to a PlayStation Vita and installed, or used with a [Vita3K](https://vita3k.org/) emulator. ## Testing -Currently there is no support to run the rustc test suite for this target. +The default Rust test runner is supported, and tests can be compiled to an elf and packed to a *.vpk file using `cargo-vita` tool. Filtering tests is not currently supported since passing command-line arguments to the executable is not supported on Vita, so the runner will always execute all tests. + +The Rust test suite for `library/std` is not yet supported. ## Cross-compilation -This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation. +This target can be cross-compiled from `x86_64` on Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 199b5d69a1c7..41602dec44c4 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -628,10 +628,10 @@ Using this flag looks like this: ```bash $ rustdoc src/lib.rs -Z unstable-options \ - --check-cfg='names()' --check-cfg='values(feature, "foo", "bar")' + --check-cfg='cfg(feature, values("foo", "bar"))' ``` -The example above check every well known names (`target_os`, `doc`, `test`, ... via `names()`) +The example above check every well known names and values (`target_os`, `doc`, `test`, ...) and check the values of `feature`: `foo` and `bar`. ### `--generate-link-to-definition`: Generate links on types in source code diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 10f0fbc50626..ca18ec567a4f 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -10,18 +10,185 @@ This feature allows you to enable complete or partial checking of configuration. check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is. -`--check-cfg` option can take one of two forms: +`--check-cfg` option take one form: -1. `--check-cfg names(...)` enables checking condition names. -2. `--check-cfg values(...)` enables checking the values within list-valued conditions. - -These two options are independent. `names` checks only the namespace of condition names -while `values` checks only the namespace of the values of list-valued conditions. +1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions. NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to -pass all expected names and values using `names(...)` and `values(...)`. +pass all expected names and values using `cfg(...)`. -## The `names(...)` form +## The `cfg(...)` form + +The `cfg(...)` form enables checking the values within list-valued conditions. It has this +basic form: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))' +``` + +where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal +string. `name` specifies the name of the condition, such as `feature` or `my_cfg`. + +When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]` +attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]` +and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the +list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` +lint diagnostic. The default diagnostic level for this lint is `Warn`. + +To enable checking of values, but to provide an empty set of expected values, use these forms: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN)' +rustc --check-cfg 'cfg(name1, ..., nameN, values())' +``` + +To enable checking of name but not values (i.e. unknown expected values), use this form: + +```bash +rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))' +``` + +The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for +different names. If it is repeated for the same condition name, then the sets of values for that +condition are merged together (presedence is given to `any()`). + +## Well known names and values + +`rustc` has a internal list of well known names and their corresponding values. +Those well known names and values follows the same stability as what they refer to. + +Well known values checking is always enabled as long as a `--check-cfg` argument is present. + +Well known names checking is always enable as long as a `--check-cfg` argument is present +**unless** any `cfg(any())` argument is passed. + +To disable checking of well known names, use this form: + +```bash +rustc --check-cfg 'cfg(any())' +``` + +NOTE: If one want to enable values and names checking without having any cfg to declare, one +can use an empty `cfg()` argument. + +## Examples + +Consider this command line: + +```bash +rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \ + --cfg 'feature="lion"' -Z unstable-options \ + example.rs +``` + +This command line indicates that this crate has two features: `lion` and `zebra`. The `lion` +feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and +values are enabled by default. Consider compiling this code: + +```rust +// This is expected, and tame_lion() will be compiled +#[cfg(feature = "lion")] +fn tame_lion(lion: Lion) {} + +// This is expected, and ride_zebra() will NOT be compiled. +#[cfg(feature = "zebra")] +fn ride_zebra(zebra: Zebra) {} + +// This is UNEXPECTED, and will cause a compiler warning (by default). +#[cfg(feature = "platypus")] +fn poke_platypus() {} + +// This is UNEXPECTED, because 'feechure' is not a known condition name, +// and will cause a compiler warning (by default). +#[cfg(feechure = "lion")] +fn tame_lion() {} + +// This is UNEXPECTED, because 'windows' is a well known condition name, +// and because 'windows' doens't take any values, +// and will cause a compiler warning (by default). +#[cfg(windows = "unix")] +fn tame_windows() {} +``` + +### Example: Checking condition names, but not values + +```bash +# This turns on checking for condition names, but not values, such as 'feature' values. +rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \ + --cfg has_feathers -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg() +fn do_embedded() {} // and because names exhaustiveness was not disabled + +#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg() +fn do_features() {} // and because names exhaustiveness was not disbaled + +#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg() + // and because no value checking was enable for "has_feathers" + // no warning is emitted for the value "zapping" +fn do_zapping() {} + +#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and + // "has_mumble_frotz" was not provided in cfg() +fn do_mumble_frotz() {} +``` + +### Example: Checking feature values, but not condition names + +```bash +# This turns on checking for feature values, but not for condition names. +rustc --check-cfg 'configure(feature, values("zapping", "lasers"))' \ + --check-cfg 'cfg(any())' \ + --cfg 'feature="zapping"' -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was + // disabled by 'cfg(any())' +fn do_embedded() {} + +#[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name + // checking is performed +fn do_features() {} + +#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list +fn shoot_lasers() {} + +#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the + // cfg(feature) list +fn write_shakespeare() {} +``` + +### Example: Checking both condition names and feature values + +```bash +# This turns on checking for feature values and for condition names. +rustc --check-cfg 'cfg(is_embedded, has_feathers)' \ + --check-cfg 'cfg(feature, values("zapping", "lasers"))' \ + --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options +``` + +```rust +#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg() +fn do_embedded() {} // and doesn't take any value + +#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg() +fn do_features() {} // and deosn't take any value + +#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided +fn do_mumble_frotz() {} + +#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list +fn shoot_lasers() {} + +#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in + // the cfg(feature) list +fn write_shakespeare() {} +``` + +## The deprecated `names(...)` form The `names(...)` form enables checking the names. This form uses a named list: @@ -56,7 +223,7 @@ The first form enables checking condition names, while specifying that there are condition names (outside of the set of well-known names defined by `rustc`). Omitting the `--check-cfg 'names(...)'` option does not enable checking condition names. -## The `values(...)` form +## The deprecated `values(...)` form The `values(...)` form enables checking the values within list-valued conditions. It has this form: @@ -87,120 +254,3 @@ condition are merged together. If `values()` is specified, then `rustc` will enable the checking of well-known values defined by itself. Note that it's necessary to specify the `values()` form to enable the checking of well known values, specifying the other forms doesn't implicitly enable it. - -## Examples - -Consider this command line: - -```bash -rustc --check-cfg 'names(feature)' \ - --check-cfg 'values(feature, "lion", "zebra")' \ - --cfg 'feature="lion"' -Z unstable-options \ - example.rs -``` - -This command line indicates that this crate has two features: `lion` and `zebra`. The `lion` -feature is enabled, while the `zebra` feature is disabled. Consider compiling this code: - -```rust -// This is expected, and tame_lion() will be compiled -#[cfg(feature = "lion")] -fn tame_lion(lion: Lion) {} - -// This is expected, and ride_zebra() will NOT be compiled. -#[cfg(feature = "zebra")] -fn ride_zebra(zebra: Zebra) {} - -// This is UNEXPECTED, and will cause a compiler warning (by default). -#[cfg(feature = "platypus")] -fn poke_platypus() {} - -// This is UNEXPECTED, because 'feechure' is not a known condition name, -// and will cause a compiler warning (by default). -#[cfg(feechure = "lion")] -fn tame_lion() {} -``` - -> Note: The `--check-cfg names(feature)` option is necessary only to enable checking the condition -> name, as in the last example. `feature` is a well-known (always-expected) condition name, and so -> it is not necessary to specify it in a `--check-cfg 'names(...)'` option. That option can be -> shortened to > `--check-cfg names()` in order to enable checking well-known condition names. - -### Example: Checking condition names, but not values - -```bash -# This turns on checking for condition names, but not values, such as 'feature' values. -rustc --check-cfg 'names(is_embedded, has_feathers)' \ - --cfg has_feathers -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names() -fn do_embedded() {} - -#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names() -fn do_features() {} - -#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names() - // and because no value checking was enable for "has_feathers" - // no warning is emitted for the value "zapping" -fn do_zapping() {} - -#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and - // "has_mumble_frotz" was not provided in names() -fn do_mumble_frotz() {} -``` - -### Example: Checking feature values, but not condition names - -```bash -# This turns on checking for feature values, but not for condition names. -rustc --check-cfg 'values(feature, "zapping", "lasers")' \ - --cfg 'feature="zapping"' -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was not - // enable (ie not names()) -fn do_embedded() {} - -#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name - // checking is performed -fn do_features() {} - - -#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list -fn shoot_lasers() {} - -#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the - // --check-cfg values(feature) list -fn write_shakespeare() {} -``` - -### Example: Checking both condition names and feature values - -```bash -# This turns on checking for feature values and for condition names. -rustc --check-cfg 'names(is_embedded, has_feathers)' \ - --check-cfg 'values(feature, "zapping", "lasers")' \ - --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options -``` - -```rust -#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in names() -fn do_embedded() {} - -#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in names() -fn do_features() {} - -#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the - // --check-cfg names(...) list -fn do_mumble_frotz() {} - -#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list -fn shoot_lasers() {} - -#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in - // the values(feature) list -fn write_shakespeare() {} -``` diff --git a/src/llvm-project b/src/llvm-project index d404cba4e39d..febc39711a7c 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit d404cba4e39df595710869988ded7cbe1104b52f +Subproject commit febc39711a7c91560eb0f0980916ae23c343b99d diff --git a/src/tools/cargo b/src/tools/cargo index 6fa6fdc7606c..8eb8acbb116e 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 6fa6fdc7606cfa664f9bee2fb33ee2ed904f4e88 +Subproject commit 8eb8acbb116e7923ea2ce33a50109933ed5ab375 diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 14877385646a..5134cf66050c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -701,7 +701,7 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { if let Some(parent) = get_parent_expr(cx, e) - && parent.span.ctxt() == e.span.ctxt() + && parent.span.eq_ctxt(e.span) { match parent.kind { ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _) diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 6197b5b19eb4..70a467dde613 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -241,7 +241,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio }, ], _, - ) if key_span.ctxt() == expr.span.ctxt() => { + ) if key_span.eq_ctxt(expr.span) => { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; let expr = ContainsExpr { negated, diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index d03480c21084..4ebf0e9667df 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -274,7 +274,7 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { for element in array { if_chain! { if let ExprKind::Binary(ref op, ref lhs, _) = element.kind; - if has_unary_equivalent(op.node) && lhs.span.ctxt() == op.span.ctxt(); + if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span); let space_span = lhs.span.between(op.span); if let Some(space_snippet) = snippet_opt(cx, space_span); let lint_span = lhs.span.with_lo(lhs.span.hi()); diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs index 4e9d77ea156a..79d728a021c3 100644 --- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs @@ -31,7 +31,7 @@ impl LateLintPass<'_> for UnderscoreTyped { if !in_external_macro(cx.tcx.sess, local.span); if let Some(ty) = local.ty; // Ensure that it has a type defined if let TyKind::Infer = &ty.kind; // that type is '_' - if local.span.ctxt() == ty.span.ctxt(); + if local.span.eq_ctxt(ty.span); then { // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 2117308cd400..86bbdb4ea199 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -59,7 +59,7 @@ impl<'tcx> QuestionMark { let Some(init) = local.init && local.els.is_none() && local.ty.is_none() && - init.span.ctxt() == stmt.span.ctxt() && + init.span.eq_ctxt(stmt.span) && let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) { match if_let_or_match { diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 33a052c41a38..29b935fb61a8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -57,7 +57,7 @@ fn check_arm<'tcx>( } }, }; - if outer_pat.span.ctxt() == inner_scrutinee.span.ctxt(); + if outer_pat.span.eq_ctxt(inner_scrutinee.span); // match expression must be a local binding // match { .. } if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)); diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 6b611f567ae2..781ee138c76f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -119,7 +119,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX { format!("({scrutinee_str})") } else { scrutinee_str.into() @@ -130,7 +130,7 @@ where if_chain! { if !some_expr.needs_unsafe_block; if let Some(func) = can_pass_as_func(cx, id, some_expr.expr); - if func.span.ctxt() == some_expr.expr.span.ctxt(); + if func.span.eq_ctxt(some_expr.expr.span); then { snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 5464e455dea4..e70a1bc98799 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -56,7 +56,7 @@ pub(super) fn check<'tcx>( // lint, with note if neither arg is > 1 line and both map() and // unwrap_or_else() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt(); + let same_span = map_arg.span.eq_ctxt(unwrap_arg.span); if same_span && !multiline { let var_snippet = snippet(cx, recv.span, ".."); span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 7b0f7eaf1f06..0e834fb3ac76 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -125,7 +125,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind; if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; - if expr.span.ctxt() == inner_expr.span.ctxt(); + if expr.span.eq_ctxt(inner_expr.span); let expr_ty = cx.typeck_results().expr_ty(expr); let inner_ty = cx.typeck_results().expr_ty(inner_expr); if expr_ty == inner_ty; diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs index d47728f190ab..e94e45899660 100644 --- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { || (path.ident.name == sym!(set_mode) && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())); if let ExprKind::Lit(_) = param.kind; - if param.span.ctxt() == expr.span.ctxt(); + if param.span.eq_ctxt(expr.span); then { let Some(snip) = snippet_opt(cx, param.span) else { @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE); if let ExprKind::Lit(_) = param.kind; - if param.span.ctxt() == expr.span.ctxt(); + if param.span.eq_ctxt(expr.span); if let Some(snip) = snippet_opt(cx, param.span); if !snip.starts_with("0o"); then { diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 534b2762ba76..8193057a6eb2 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { let Some(body_expr) = desugar_async_block(cx, expr) && let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. - expr.span.ctxt() == body_expr.span.ctxt() && + expr.span.eq_ctxt(body_expr.span) && // An async block does not have immediate side-effects from a `.await` point-of-view. (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index db870ec4c5b6..12da29f11089 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -50,7 +50,7 @@ impl EarlyLintPass for DerefAddrOf { if_chain! { if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind; if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind; - if deref_target.span.ctxt() == e.span.ctxt(); + if deref_target.span.eq_ctxt(e.span); if !addrof_target.span.from_expansion(); then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs index 8e156b8829b9..39cd289b67ad 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -33,7 +33,7 @@ impl LateLintPass<'_> for ConfusingXorAndPow { if !in_external_macro(cx.sess(), expr.span) && let ExprKind::Binary(op, left, right) = &expr.kind && op.node == BinOpKind::BitXor - && left.span.ctxt() == right.span.ctxt() + && left.span.eq_ctxt(right.span) && let ExprKind::Lit(lit_left) = &left.kind && let ExprKind::Lit(lit_right) = &right.kind && matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..)) diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index eaf590f6ad77..46ce4ffdce5d 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -245,7 +245,7 @@ impl<'a> PanicExpn<'a> { return None; }; let result = match name { - "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty, + "panic" if arg.span.eq_ctxt(expr.span) => Self::Empty, "panic" | "panic_str" => Self::Str(arg), "panic_display" | "panic_cold_display" => { let ExprKind::AddrOf(_, _, e) = &arg.kind else { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2d305a63eca1..673b259523e1 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1133,7 +1133,7 @@ pub fn make_projection<'tcx>( #[cfg(debug_assertions)] assert_generic_args_match(tcx, assoc_item.def_id, args); - Some(tcx.mk_alias_ty(assoc_item.def_id, args)) + Some(ty::AliasTy::new(tcx, assoc_item.def_id, args)) } helper( tcx, diff --git a/src/tools/clippy/tests/ui/builtin_type_shadow.stderr b/src/tools/clippy/tests/ui/builtin_type_shadow.stderr index cb8462182b89..e051c00eb8d2 100644 --- a/src/tools/clippy/tests/ui/builtin_type_shadow.stderr +++ b/src/tools/clippy/tests/ui/builtin_type_shadow.stderr @@ -13,7 +13,7 @@ error[E0308]: mismatched types LL | fn foo(a: u32) -> u32 { | --- --- expected `u32` because of return type | | - | this type parameter + | expected this type parameter LL | 42 | ^^ expected type parameter `u32`, found integer | diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index bb1fa6e9237d..31c6353e6754 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -11,6 +11,7 @@ colored = "2" diff = "0.1.10" unified-diff = "0.2.1" getopts = "0.2" +indexmap = "2.0.0" miropt-test-tools = { path = "../miropt-test-tools" } build_helper = { path = "../build_helper" } tracing = "0.1" diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7b42d8e9b584..875671c64e00 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4258,6 +4258,39 @@ impl<'test> TestCx<'test> { V0_BACK_REF_RE.replace_all(&normalized, V0_BACK_REF_PLACEHOLDER).into_owned(); } + // AllocId are numbered globally in a compilation session. This can lead to changes + // depending on the exact compilation flags and host architecture. Meanwhile, we want + // to keep them numbered, to see if the same id appears multiple times. + // So we remap to deterministic numbers that only depend on the subset of allocations + // that actually appear in the output. + // We use uppercase ALLOC to distinguish from the non-normalized version. + { + let mut seen_allocs = indexmap::IndexSet::new(); + + // The alloc-id appears in pretty-printed allocations. + let re = Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?─*╼").unwrap(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + // Renumber the captured index. + let index = caps.get(2).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + let offset = caps.get(3).map_or("", |c| c.as_str()); + // Do not bother keeping it pretty, just make it deterministic. + format!("╾ALLOC{index}{offset}╼") + }) + .into_owned(); + + // The alloc-id appears in a sentence. + let re = Regex::new(r"\balloc([0-9]+)\b").unwrap(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + let index = caps.get(1).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + format!("ALLOC{index}") + }) + .into_owned(); + } + // Custom normalization rules for rule in custom_rules { let re = Regex::new(&rule.0).expect("bad regex in custom normalization rule"); diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index a7c9d720c0cf..4664cc39820f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c07693c1608258f3577eb15057fc0744fa924ae9 +c104861b7b51d2c28e7023e7e53db16cc6677e29 diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs index 4fd0af35304e..0bdea1576339 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/intptrcast.rs @@ -119,24 +119,14 @@ impl<'mir, 'tcx> GlobalStateInner { Ok(()) } - pub fn ptr_from_addr_transmute( - _ecx: &MiriInterpCx<'mir, 'tcx>, - addr: u64, - ) -> Pointer> { - trace!("Transmuting {:#x} to a pointer", addr); - - // We consider transmuted pointers to be "invalid" (`None` provenance). - Pointer::new(None, Size::from_bytes(addr)) - } - pub fn ptr_from_addr_cast( ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64, ) -> InterpResult<'tcx, Pointer>> { trace!("Casting {:#x} to a pointer", addr); + // Potentially emit a warning. let global_state = ecx.machine.intptrcast.borrow(); - match global_state.provenance_mode { ProvenanceMode::Default => { // The first time this happens at a particular location, print a warning. @@ -158,7 +148,12 @@ impl<'mir, 'tcx> GlobalStateInner { ProvenanceMode::Permissive => {} } - // This is how wildcard pointers are born. + // We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is + // completely legal to do a cast and then `wrapping_offset` to another allocation and only + // *then* do a memory access. So the allocation that the pointer happens to point to on a + // cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that + // *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed) + // allocation it might be referencing. Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr))) } @@ -219,22 +214,24 @@ impl<'mir, 'tcx> GlobalStateInner { }) } - /// Convert a relative (tcx) pointer to an absolute address. - pub fn rel_ptr_to_addr( + /// Convert a relative (tcx) pointer to a Miri pointer. + pub fn ptr_from_rel_ptr( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, - ) -> InterpResult<'tcx, u64> { + tag: BorTag, + ) -> InterpResult<'tcx, Pointer> { let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); - Ok(dl.overflowing_offset(base_addr, offset.bytes()).0) + let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0; + Ok(Pointer::new(Provenance::Concrete { alloc_id, tag }, Size::from_bytes(absolute_addr))) } /// When a pointer is used for a memory access, this computes where in which allocation the /// access is going. - pub fn abs_ptr_to_rel( + pub fn ptr_get_alloc( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, ) -> Option<(AllocId, Size)> { @@ -252,12 +249,11 @@ impl<'mir, 'tcx> GlobalStateInner { let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap(); // Wrapping "addr - base_addr" - let dl = ecx.data_layout(); #[allow(clippy::cast_possible_wrap)] // we want to wrap here let neg_base_addr = (base_addr as i64).wrapping_neg(); Some(( alloc_id, - Size::from_bytes(dl.overflowing_signed_offset(addr.bytes(), neg_base_addr).0), + Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0), )) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 864374bfdf28..0ade43d4a8dc 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -168,11 +168,29 @@ impl fmt::Display for MiriMemoryKind { /// Pointer provenance. #[derive(Clone, Copy)] pub enum Provenance { + /// For pointers with concrete provenance. we exactly know which allocation they are attached to + /// and what their borrow tag is. Concrete { alloc_id: AllocId, /// Borrow Tracker tag. tag: BorTag, }, + /// Pointers with wildcard provenance are created on int-to-ptr casts. According to the + /// specification, we should at that point angelically "guess" a provenance that will make all + /// future uses of this pointer work, if at all possible. Of course such a semantics cannot be + /// actually implemented in Miri. So instead, we approximate this, erroring on the side of + /// accepting too much code rather than rejecting correct code: a pointer with wildcard + /// provenance "acts like" any previously exposed pointer. Each time it is used, we check + /// whether *some* exposed pointer could have done what we want to do, and if the answer is yes + /// then we allow the access. This allows too much code in two ways: + /// - The same wildcard pointer can "take the role" of multiple different exposed pointers on + /// subsequenct memory accesses. + /// - In the aliasing model, we don't just have to know the borrow tag of the pointer used for + /// the access, we also have to update the aliasing state -- and that update can be very + /// different depending on which borrow tag we pick! Stacked Borrows has support for this by + /// switching to a stack that is only approximately known, i.e. we overapproximate the effect + /// of using *any* exposed pointer for this access, and only keep information about the borrow + /// stack that would be true with all possible choices. Wildcard, } @@ -1125,19 +1143,16 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { _ => {} } } - let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr)?; let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() }; - Ok(Pointer::new( - Provenance::Concrete { alloc_id: ptr.provenance, tag }, - Size::from_bytes(absolute_addr), - )) + intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag) } + /// Called on `usize as ptr` casts. #[inline(always)] fn ptr_from_addr_cast( ecx: &MiriInterpCx<'mir, 'tcx>, @@ -1146,6 +1161,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr) } + /// Called on `ptr as usize` casts. + /// (Actually computing the resulting `usize` doesn't need machine help, + /// that's just `Scalar::try_to_int`.) fn expose_ptr( ecx: &mut InterpCx<'mir, 'tcx, Self>, ptr: Pointer, @@ -1163,11 +1181,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { /// Convert a pointer with provenance into an allocation-offset pair, /// or a `None` with an absolute address if that conversion is not possible. + /// + /// This is called when a pointer is about to be used for memory access, + /// an in-bounds check, or anything else that requires knowing which allocation it points to. + /// The resulting `AllocId` will just be used for that one step and the forgotten again + /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be + /// stored in machine state). fn ptr_get_alloc( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { - let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr); + let rel = intptrcast::GlobalStateInner::ptr_get_alloc(ecx, ptr); rel.map(|(alloc_id, size)| { let tag = match ptr.provenance { diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index b22a26ce36f1..9520f9327797 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -1,6 +1,7 @@ // assembly-output: emit-asm // compile-flags: --target armv7-unknown-linux-gnueabihf // compile-flags: -C target-feature=+neon +// compile-flags: -C opt-level=0 // needs-llvm-components: arm #![feature(no_core, lang_items, rustc_attrs, repr_simd)] diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs index 65728a155166..248026034526 100644 --- a/tests/assembly/closure-inherit-target-feature.rs +++ b/tests/assembly/closure-inherit-target-feature.rs @@ -22,6 +22,7 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { f(x, y) } +#[no_mangle] #[target_feature(enable = "sse4.1")] pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 { let f = { diff --git a/tests/assembly/dwarf5.rs b/tests/assembly/dwarf5.rs index f41e6bd55be7..253baafb8873 100644 --- a/tests/assembly/dwarf5.rs +++ b/tests/assembly/dwarf5.rs @@ -1,6 +1,6 @@ // Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5. // assembly-output: emit-asm -// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 +// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 -Copt-level=0 // needs-llvm-components: x86 #![feature(no_core, lang_items)] diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs new file mode 100644 index 000000000000..fca2c85d5a62 --- /dev/null +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -0,0 +1,406 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// only-windows +// only-msvc +// ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic +// [none] compile-flags: -Z stack-protector=none +// compile-flags: -C opt-level=2 -Z merge-functions=disabled + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 7]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + let x = String::new(); + f(&x); + + // Taking the address of the local variable `x` leads to stack smash + // protection with the `strong` heuristic, but not with the `basic` + // heuristic. It does not matter that the reference is not mut. + // + // An interesting note is that a similar function in C++ *would* be + // protected by the `basic` heuristic, because `std::string` has a char + // array internally as a small object optimization: + // ``` + // cat < + // void f(void (*g)(const std::string&)) { + // std::string x; + // g(x); + // } + // EOF + // ``` + // + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// CHECK-LABEL: local_var_addr_taken_used_locally_only +#[no_mangle] +pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// The question then is: in what ways can Rust code generate array-`alloca` +// LLVM instructions? This appears to only be generated by +// rustc_codegen_ssa::traits::Builder::array_alloca() through +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT +// this is support for the "unsized locals" unstable feature: +// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // alloca, and is therefore not protected by the `strong` or `basic` + // heuristics. + + + // We should have a __security_check_cookie call in `all` and `strong` modes but + // LLVM does not support generating stack protectors in functions with funclet + // based EH personalities. + // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 + // all-NOT: __security_check_cookie + // strong-NOT: __security_check_cookie + + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // We should have a __security_check_cookie call in `all`, `strong` and `basic` modes but + // LLVM does not support generating stack protectors in functions with funclet + // based EH personalities. + // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 + // all-NOT: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs new file mode 100644 index 000000000000..d9abf554a92d --- /dev/null +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -0,0 +1,414 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// only-windows +// only-msvc +// ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic +// [none] compile-flags: -Z stack-protector=none +// compile-flags: -C opt-level=2 -Z merge-functions=disabled + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 7]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + // CHECK-DAG: .seh_endprologue + let x = String::new(); + f(&x); + + // Taking the address of the local variable `x` leads to stack smash + // protection with the `strong` heuristic, but not with the `basic` + // heuristic. It does not matter that the reference is not mut. + // + // An interesting note is that a similar function in C++ *would* be + // protected by the `basic` heuristic, because `std::string` has a char + // array internally as a small object optimization: + // ``` + // cat < + // void f(void (*g)(const std::string&)) { + // std::string x; + // g(x); + // } + // EOF + // ``` + // + + // We should have a __security_check_cookie call in `all` and `strong` modes but + // LLVM does not support generating stack protectors in functions with funclet + // based EH personalities. + // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 + // all-NOT: __security_check_cookie + // strong-NOT: __security_check_cookie + + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie + + // CHECK-DAG: .seh_endproc +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// CHECK-LABEL: local_var_addr_taken_used_locally_only +#[no_mangle] +pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __security_check_cookie + // strong: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// The question then is: in what ways can Rust code generate array-`alloca` +// LLVM instructions? This appears to only be generated by +// rustc_codegen_ssa::traits::Builder::array_alloca() through +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT +// this is support for the "unsized locals" unstable feature: +// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // alloca, and is therefore not protected by the `strong` or `basic` + // heuristics. + + + // We should have a __security_check_cookie call in `all` and `strong` modes but + // LLVM does not support generating stack protectors in functions with funclet + // based EH personalities. + // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 + // all-NOT: __security_check_cookie + // strong-NOT: __security_check_cookie + + // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} + +// CHECK-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // We should have a __security_check_cookie call in `all`, `strong` and `basic` modes but + // LLVM does not support generating stack protectors in functions with funclet + // based EH personalities. + // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 + // all-NOT: __security_check_cookie + // strong-NOT: __security_check_cookie + // basic-NOT: __security_check_cookie + + // none-NOT: __security_check_cookie + // missing-NOT: __security_check_cookie +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index e46b902df079..ca566b6e46ae 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -1,7 +1,7 @@ // revisions: all strong basic none missing // assembly-output: emit-asm // ignore-macos slightly different policy on stack protection of arrays -// ignore-windows stack check code uses different function names +// ignore-msvc stack check code uses different function names // ignore-nvptx64 stack protector is not supported // ignore-wasm32-bare // [all] compile-flags: -Z stack-protector=all diff --git a/tests/codegen-units/item-collection/asm-sym.rs b/tests/codegen-units/item-collection/asm-sym.rs index 8bafb95bc16d..4b05b771a9b2 100644 --- a/tests/codegen-units/item-collection/asm-sym.rs +++ b/tests/codegen-units/item-collection/asm-sym.rs @@ -6,15 +6,18 @@ pub unsafe fn f() { //~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External] static S: usize = 1; //~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External] + #[inline(never)] fn fun() {} core::arch::asm!("/* {0} {1} */", sym S, sym fun); } //~ MONO_ITEM fn g @@ asm_sym-cgu.0[External] +#[inline(never)] pub unsafe fn g() { //~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal] static S: usize = 2; //~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal] + #[inline(never)] fn fun() {} core::arch::asm!("/* {0} {1} */", sym S, sym fun); } diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs index ecea26dc4be4..e94dded55cff 100644 --- a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs +++ b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs @@ -1,3 +1,5 @@ +// compile-flags: -Copt-level=0 + #![crate_type = "lib"] pub trait Trait : Sized { diff --git a/tests/codegen-units/item-collection/cross-crate-trait-method.rs b/tests/codegen-units/item-collection/cross-crate-trait-method.rs index b7216a143180..778b3820f18e 100644 --- a/tests/codegen-units/item-collection/cross-crate-trait-method.rs +++ b/tests/codegen-units/item-collection/cross-crate-trait-method.rs @@ -1,4 +1,4 @@ -// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no +// compile-flags:-Zprint-mono-items=eager -Zinline-mir=no -Copt-level=0 #![deny(dead_code)] #![feature(start)] diff --git a/tests/codegen-units/item-collection/items-within-generic-items.rs b/tests/codegen-units/item-collection/items-within-generic-items.rs index d37d7f7d9b2b..bb1a3be36c5c 100644 --- a/tests/codegen-units/item-collection/items-within-generic-items.rs +++ b/tests/codegen-units/item-collection/items-within-generic-items.rs @@ -1,4 +1,4 @@ -// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zprint-mono-items=eager -Copt-level=0 #![deny(dead_code)] #![feature(start)] diff --git a/tests/codegen-units/item-collection/unreferenced-const-fn.rs b/tests/codegen-units/item-collection/unreferenced-const-fn.rs index 17b92eae00d0..5f59d801504e 100644 --- a/tests/codegen-units/item-collection/unreferenced-const-fn.rs +++ b/tests/codegen-units/item-collection/unreferenced-const-fn.rs @@ -4,6 +4,7 @@ #![crate_type = "rlib"] //~ MONO_ITEM fn foo @@ unreferenced_const_fn-cgu.0[External] +#[inline(never)] pub const fn foo(x: u32) -> u32 { x + 0xf00 } diff --git a/tests/codegen/asm-sanitize-llvm.rs b/tests/codegen/asm-sanitize-llvm.rs index 6dcacd08cacd..41bed98038ec 100644 --- a/tests/codegen/asm-sanitize-llvm.rs +++ b/tests/codegen/asm-sanitize-llvm.rs @@ -1,5 +1,5 @@ // FIXME(nagisa): remove the flags below once all targets support `asm!`. -// compile-flags: --target x86_64-unknown-linux-gnu +// compile-flags: --target x86_64-unknown-linux-gnu -Copt-level=0 // needs-llvm-components: x86 // Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs index 690505fd72bd..29defe68f8b8 100644 --- a/tests/codegen/async-fn-debug-awaitee-field.rs +++ b/tests/codegen/async-fn-debug-awaitee-field.rs @@ -3,7 +3,7 @@ // extensions rely on the field having this name. // ignore-tidy-linelength -// compile-flags: -C debuginfo=2 --edition=2018 +// compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/debug-linkage-name.rs b/tests/codegen/debug-linkage-name.rs index 9011a7da51db..9bf4d521fc01 100644 --- a/tests/codegen/debug-linkage-name.rs +++ b/tests/codegen/debug-linkage-name.rs @@ -1,8 +1,8 @@ // Verifies that linkage name is omitted when it is // the same as variable / function name. // -// compile-flags: -C no-prepopulate-passes -// compile-flags: -C debuginfo=2 +// compile-flags: -C no-prepopulate-passes -Copt-level=0 +// compile-flags: -C debuginfo=2 -Copt-level=0 #![crate_type = "lib"] pub mod xyz { diff --git a/tests/codegen/default-requires-uwtable.rs b/tests/codegen/default-requires-uwtable.rs index 5d77d3f14bb1..26424f03568b 100644 --- a/tests/codegen/default-requires-uwtable.rs +++ b/tests/codegen/default-requires-uwtable.rs @@ -1,5 +1,5 @@ // revisions: WINDOWS ANDROID -// compile-flags: -C panic=abort +// compile-flags: -C panic=abort -Copt-level=0 // [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc // [WINDOWS] needs-llvm-components: x86 // [ANDROID] compile-flags: --target=armv7-linux-androideabi diff --git a/tests/codegen/drop.rs b/tests/codegen/drop.rs index 3615ef47b531..14b5840e2fe2 100644 --- a/tests/codegen/drop.rs +++ b/tests/codegen/drop.rs @@ -7,10 +7,12 @@ struct SomeUniqueName; impl Drop for SomeUniqueName { + #[inline(never)] fn drop(&mut self) { } } +#[inline(never)] pub fn possibly_unwinding() { } diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs index 637c4234654b..5791ae47937b 100644 --- a/tests/codegen/force-frame-pointers.rs +++ b/tests/codegen/force-frame-pointers.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/force-unwind-tables.rs b/tests/codegen/force-unwind-tables.rs index 4c0a5602c6da..c904978c9ff2 100644 --- a/tests/codegen/force-unwind-tables.rs +++ b/tests/codegen/force-unwind-tables.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y +// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs index e3d8caa49d45..ffae99e0f24e 100644 --- a/tests/codegen/inline-function-args-debug-info.rs +++ b/tests/codegen/inline-function-args-debug-info.rs @@ -6,6 +6,7 @@ #![crate_type = "lib"] +#[inline(never)] pub fn outer_function(x: usize, y: usize) -> usize { inner_function(x, y) + 1 } @@ -13,8 +14,8 @@ pub fn outer_function(x: usize, y: usize) -> usize { #[inline] fn inner_function(aaaa: usize, bbbb: usize) -> usize { // CHECK: !DILocalVariable(name: "aaaa", arg: 1 - // CHECK-SAME: line: 14 + // CHECK-SAME: line: 15 // CHECK: !DILocalVariable(name: "bbbb", arg: 2 - // CHECK-SAME: line: 14 + // CHECK-SAME: line: 15 aaaa + bbbb } diff --git a/tests/codegen/instrument-mcount.rs b/tests/codegen/instrument-mcount.rs index b26076e7a7bf..50823775a41a 100644 --- a/tests/codegen/instrument-mcount.rs +++ b/tests/codegen/instrument-mcount.rs @@ -1,5 +1,5 @@ // -// compile-flags: -Z instrument-mcount +// compile-flags: -Z instrument-mcount -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/basic.rs b/tests/codegen/instrument-xray/basic.rs index d3e49d531744..5da878474f2e 100644 --- a/tests/codegen/instrument-xray/basic.rs +++ b/tests/codegen/instrument-xray/basic.rs @@ -1,7 +1,7 @@ // Checks that `-Z instrument-xray` produces expected instrumentation. // // needs-xray -// compile-flags: -Z instrument-xray=always +// compile-flags: -Z instrument-xray=always -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/options-combine.rs b/tests/codegen/instrument-xray/options-combine.rs index f7e500b65f62..d1e56586279a 100644 --- a/tests/codegen/instrument-xray/options-combine.rs +++ b/tests/codegen/instrument-xray/options-combine.rs @@ -1,9 +1,9 @@ // Checks that `-Z instrument-xray` options can be specified multiple times. // // needs-xray -// compile-flags: -Z instrument-xray=skip-exit -// compile-flags: -Z instrument-xray=instruction-threshold=123 -// compile-flags: -Z instrument-xray=instruction-threshold=456 +// compile-flags: -Z instrument-xray=skip-exit -Copt-level=0 +// compile-flags: -Z instrument-xray=instruction-threshold=123 -Copt-level=0 +// compile-flags: -Z instrument-xray=instruction-threshold=456 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/instrument-xray/options-override.rs b/tests/codegen/instrument-xray/options-override.rs index 00f81837902d..b1fc4c966dcb 100644 --- a/tests/codegen/instrument-xray/options-override.rs +++ b/tests/codegen/instrument-xray/options-override.rs @@ -1,8 +1,8 @@ // Checks that the last `-Z instrument-xray` option wins. // // needs-xray -// compile-flags: -Z instrument-xray=always -// compile-flags: -Z instrument-xray=never +// compile-flags: -Z instrument-xray=always -Copt-level=0 +// compile-flags: -Z instrument-xray=never -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/panic-unwind-default-uwtable.rs b/tests/codegen/panic-unwind-default-uwtable.rs index 4c85008cf359..b78b159d20d5 100644 --- a/tests/codegen/panic-unwind-default-uwtable.rs +++ b/tests/codegen/panic-unwind-default-uwtable.rs @@ -1,4 +1,4 @@ -// compile-flags: -C panic=unwind -C no-prepopulate-passes +// compile-flags: -C panic=unwind -C no-prepopulate-passes -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs index 47243bece98f..b39718a8d08c 100644 --- a/tests/codegen/personality_lifetimes.rs +++ b/tests/codegen/personality_lifetimes.rs @@ -9,10 +9,12 @@ struct S; impl Drop for S { + #[inline(never)] fn drop(&mut self) { } } +#[inline(never)] fn might_unwind() { } diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs index 084d8bf803c8..f16890afad08 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs @@ -1,7 +1,7 @@ // Verifies that user-defined CFI encoding for types are emitted. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 #![crate_type="lib"] #![feature(cfi_encoding, extern_types)] diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index 2d8b13e2080e..4ed7c27fc4e8 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -1,7 +1,7 @@ // Verifies that type metadata identifiers for functions are emitted correctly. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 #![crate_type="lib"] #![allow(dead_code)] diff --git a/tests/codegen/sanitizer/cfi-generalize-pointers.rs b/tests/codegen/sanitizer/cfi-generalize-pointers.rs index 677ebdb27ec5..17cb42d3e74f 100644 --- a/tests/codegen/sanitizer/cfi-generalize-pointers.rs +++ b/tests/codegen/sanitizer/cfi-generalize-pointers.rs @@ -1,7 +1,7 @@ // Verifies that pointer types are generalized. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/sanitizer/cfi-normalize-integers.rs b/tests/codegen/sanitizer/cfi-normalize-integers.rs index aa3913cb8e7d..9663aa54c28d 100644 --- a/tests/codegen/sanitizer/cfi-normalize-integers.rs +++ b/tests/codegen/sanitizer/cfi-normalize-integers.rs @@ -1,7 +1,7 @@ // Verifies that integer types are normalized. // // needs-sanitizer-cfi -// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers +// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Copt-level=0 #![crate_type="lib"] diff --git a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs index 783bc47b9d05..29d50d8df24a 100644 --- a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs +++ b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs @@ -1,6 +1,6 @@ // Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation. -// compile-flags: -Zsanitizer=kernel-address +// compile-flags: -Zsanitizer=kernel-address -Copt-level=0 // revisions: aarch64 riscv64imac riscv64gc x86_64 //[aarch64] compile-flags: --target aarch64-unknown-none //[aarch64] needs-llvm-components: aarch64 diff --git a/tests/codegen/sanitizer/memtag-attr-check.rs b/tests/codegen/sanitizer/memtag-attr-check.rs index 2fd362656d4b..3e5e14e84297 100644 --- a/tests/codegen/sanitizer/memtag-attr-check.rs +++ b/tests/codegen/sanitizer/memtag-attr-check.rs @@ -2,7 +2,7 @@ // applied when enabling the memtag sanitizer. // // needs-sanitizer-memtag -// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte +// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index d0b692434537..029cf8e7f5c9 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -2,7 +2,7 @@ // selectively disable sanitizer instrumentation. // // needs-sanitizer-address -// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +// compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 #![crate_type="lib"] #![feature(no_sanitize)] diff --git a/tests/codegen/sanitizer/safestack-attr-check.rs b/tests/codegen/sanitizer/safestack-attr-check.rs index b73ed00e7308..b19e2d131334 100644 --- a/tests/codegen/sanitizer/safestack-attr-check.rs +++ b/tests/codegen/sanitizer/safestack-attr-check.rs @@ -1,7 +1,7 @@ // This tests that the safestack attribute is applied when enabling the safe-stack sanitizer. // // needs-sanitizer-safestack -// compile-flags: -Zsanitizer=safestack +// compile-flags: -Zsanitizer=safestack -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs index 64be1127786f..6ef0f0406d20 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=md5 +// compile-flags: -g -Z src-hash-algorithm=md5 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs index 54e07152142e..ebfa3040acaf 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=sha1 +// compile-flags: -g -Z src-hash-algorithm=sha1 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs index dc7db8e23728..5ec678d55f34 100644 --- a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs +++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs @@ -1,4 +1,4 @@ -// compile-flags: -g -Z src-hash-algorithm=sha256 +// compile-flags: -g -Z src-hash-algorithm=sha256 -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen/target-cpu-on-functions.rs b/tests/codegen/target-cpu-on-functions.rs index c043eceb5cd1..d5250f22cca9 100644 --- a/tests/codegen/target-cpu-on-functions.rs +++ b/tests/codegen/target-cpu-on-functions.rs @@ -15,7 +15,8 @@ pub extern "C" fn exported() { // CHECK-LABEL: ; target_cpu_on_functions::not_exported // CHECK-NEXT: ; Function Attrs: -// CHECK-NEXT: define {{.*}}() {{.*}} #0 +// CHECK-NEXT: define {{.*}}() {{.*}} #1 +#[inline(never)] fn not_exported() {} // CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}" diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 51334c121582..71cea48c4da5 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -7,16 +7,16 @@ // are targeting older LLVM versions. Once the min supported version // is LLVM-14 we can remove the optional regex matching for this feature. -// [ENABLE_SVE] compile-flags: -C target-feature=+sve +// [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 // ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" } -// [DISABLE_SVE] compile-flags: -C target-feature=-sve +// [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 // DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } -// [DISABLE_NEON] compile-flags: -C target-feature=-neon +// [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 // DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } -// [ENABLE_NEON] compile-flags: -C target-feature=+neon +// [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/codegen/tune-cpu-on-functions.rs b/tests/codegen/tune-cpu-on-functions.rs index ed8dc0e93837..116f0772d255 100644 --- a/tests/codegen/tune-cpu-on-functions.rs +++ b/tests/codegen/tune-cpu-on-functions.rs @@ -3,7 +3,7 @@ // no-prefer-dynamic // -// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic +// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic -Copt-level=0 #![crate_type = "staticlib"] diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage-map/status-quo/issue-84561.cov-map index fe098fd396c2..01fa7ec573c5 100644 --- a/tests/coverage-map/status-quo/issue-84561.cov-map +++ b/tests/coverage-map/status-quo/issue-84561.cov-map @@ -1,11 +1,10 @@ Function name: ::eq -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 0a, 00, 13, 00, 00, 0a, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 2 +Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) -- Code(Zero) at (prev + 0, 10) to (start + 0, 19) Function name: ::fmt Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 89, 01, 09, 00, 25, 05, 00, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] diff --git a/tests/mir-opt/building/custom/consts.statics.built.after.mir b/tests/mir-opt/building/custom/consts.statics.built.after.mir index ea394c5b7276..a5cb6ff992ee 100644 --- a/tests/mir-opt/building/custom/consts.statics.built.after.mir +++ b/tests/mir-opt/building/custom/consts.statics.built.after.mir @@ -6,16 +6,16 @@ fn statics() -> () { let mut _2: *mut i32; bb0: { - _1 = const {alloc1: &i32}; - _2 = const {alloc2: *mut i32}; + _1 = const {ALLOC0: &i32}; + _2 = const {ALLOC1: *mut i32}; return; } } -alloc2 (static: T, size: 4, align: 4) { +ALLOC1 (static: T, size: 4, align: 4) { 0a 0a 0a 0a │ .... } -alloc1 (static: S, size: 4, align: 4) { +ALLOC0 (static: S, size: 4, align: 4) { 05 05 05 05 │ .... } diff --git a/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir index 9b17b4b63dd3..09a65e6e6a6e 100644 --- a/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir @@ -23,6 +23,6 @@ fn main() -> () { } } -alloc1 (size: 3, align: 1) { +ALLOC0 (size: 3, align: 1) { 66 6f 6f │ foo } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index 8c8e69595950..f20bfef8c794 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,43 +17,43 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc19─╼ 03 00 00 00 │ ╾──╼.... +ALLOC9 (static: FOO, size: 8, align: 4) { + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } -alloc19 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc6──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc10─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC0 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc6 (size: 0, align: 4) {} +ALLOC1 (size: 0, align: 4) {} -alloc10 (size: 16, align: 4) { - ╾─alloc9──╼ 03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +ALLOC2 (size: 16, align: 4) { + ╾ALLOC4╼ 03 00 00 00 ╾ALLOC5╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc9 (size: 3, align: 1) { +ALLOC4 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 62 61 72 │ bar } -alloc15 (size: 24, align: 4) { - 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─alloc17─╼ 04 00 00 00 │ ╾──╼.... +ALLOC3 (size: 24, align: 4) { + 0x00 │ ╾ALLOC6╼ 03 00 00 00 ╾ALLOC7╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾ALLOC8╼ 04 00 00 00 │ ╾──╼.... } -alloc14 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index e22547032967..263cae2f3ea5 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,47 +17,47 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc19───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC9 (static: FOO, size: 16, align: 8) { + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc19 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc6────────╼ │ ....░░░░╾──────╼ +ALLOC0 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc10───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc15───────╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc6 (size: 0, align: 8) {} +ALLOC1 (size: 0, align: 8) {} -alloc10 (size: 32, align: 8) { - 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc11───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC2 (size: 32, align: 8) { + 0x00 │ ╾ALLOC4╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC5╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc9 (size: 3, align: 1) { +ALLOC4 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +ALLOC5 (size: 3, align: 1) { 62 61 72 │ bar } -alloc15 (size: 48, align: 8) { - 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc16───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────alloc17───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC3 (size: 48, align: 8) { + 0x00 │ ╾ALLOC6╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC7╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾ALLOC8╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc14 (size: 3, align: 1) { +ALLOC6 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +ALLOC7 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index c5f6902b4b48..713abb264a70 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&u8])]}; + _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,42 +17,42 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc23─╼ 03 00 00 00 │ ╾──╼.... +ALLOC9 (static: FOO, size: 8, align: 4) { + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } -alloc23 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc10─╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc15─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼.... +ALLOC0 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc10 (size: 0, align: 4) {} +ALLOC1 (size: 0, align: 4) {} -alloc15 (size: 8, align: 4) { - ╾─alloc13─╼ ╾─alloc14─╼ │ ╾──╼╾──╼ +ALLOC2 (size: 8, align: 4) { + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } -alloc13 (size: 1, align: 1) { +ALLOC4 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 12, align: 4) { - ╾─a18+0x3─╼ ╾─alloc19─╼ ╾─a20+0x2─╼ │ ╾──╼╾──╼╾──╼ +ALLOC3 (size: 12, align: 4) { + ╾ALLOC6+0x3╼ ╾ALLOC7╼ ╾ALLOC8+0x2╼ │ ╾──╼╾──╼╾──╼ } -alloc18 (size: 4, align: 1) { +ALLOC6 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc19 (size: 1, align: 1) { +ALLOC7 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index b95b8c787487..e9d61ef120c7 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&u8])]}; + _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,45 +17,45 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +ALLOC9 (static: FOO, size: 16, align: 8) { + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc23 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc10───────╼ │ ....░░░░╾──────╼ +ALLOC0 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc15───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc10 (size: 0, align: 8) {} +ALLOC1 (size: 0, align: 8) {} -alloc15 (size: 16, align: 8) { - ╾───────alloc13───────╼ ╾───────alloc14───────╼ │ ╾──────╼╾──────╼ +ALLOC2 (size: 16, align: 8) { + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } -alloc13 (size: 1, align: 1) { +ALLOC4 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +ALLOC5 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 24, align: 8) { - 0x00 │ ╾─────alloc18+0x3─────╼ ╾───────alloc19───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc20+0x2─────╼ │ ╾──────╼ +ALLOC3 (size: 24, align: 8) { + 0x00 │ ╾ALLOC6+0x3╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾ALLOC8+0x2╼ │ ╾──────╼ } -alloc18 (size: 4, align: 1) { +ALLOC6 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc19 (size: 1, align: 1) { +ALLOC7 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +ALLOC8 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index e172c7540014..c18c067c72e7 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&Packed}; + _2 = const {ALLOC4: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,31 +17,31 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 4, align: 4) { - ╾─alloc12─╼ │ ╾──╼ +ALLOC4 (static: FOO, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } -alloc12 (size: 168, align: 1) { +ALLOC0 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc7──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾ALLOC1╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc9──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾a10+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾ALLOC2╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾ALLOC3+0x63╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } -alloc7 (size: 4, align: 4) { +ALLOC1 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc9 (fn: main) +ALLOC2 (fn: main) -alloc10 (size: 100, align: 1) { +ALLOC3 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index d5feea723e7c..6af0e3cbd94c 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&Packed}; + _2 = const {ALLOC2: &&Packed}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,13 +17,13 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 8) { - ╾───────alloc12───────╼ │ ╾──────╼ +ALLOC2 (static: FOO, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } -alloc12 (size: 180, align: 1) { +ALLOC0 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc7── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──ALLOC3── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -31,18 +31,18 @@ alloc12 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────alloc9─────╼ 00 00 ╾────alloc10+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────ALLOC4─────╼ 00 00 ╾ALLOC1+0x63╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } -alloc7 (size: 4, align: 4) { +ALLOC3 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc9 (fn: main) +ALLOC4 (fn: main) -alloc10 (size: 100, align: 1) { +ALLOC1 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 5b8d3ca78e3f..960b982242d2 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,7 +7,7 @@ promoted[0] in BAR: &[&i32; 1] = { let mut _3: &i32; bb0: { - _3 = const {alloc1: &i32}; + _3 = const {ALLOC0: &i32}; _2 = &(*_3); _1 = [move _2]; _0 = &_1; @@ -15,6 +15,6 @@ promoted[0] in BAR: &[&i32; 1] = { } } -alloc1 (static: Y, size: 4, align: 4) { +ALLOC0 (static: Y, size: 4, align: 4) { 2a 00 00 00 │ *... } diff --git a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 14d2d7fc85cf..4a93db3fcaa8 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -16,7 +16,7 @@ - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); -- _5 = const {alloc1: &i32}; +- _5 = const {ALLOC0: &i32}; - _4 = &(*_5); - _3 = [move _4]; - _2 = &_3; @@ -40,7 +40,7 @@ } - } - -- alloc1 (static: Y, size: 4, align: 4) { +- ALLOC0 (static: Y, size: 4, align: 4) { - 2a 00 00 00 │ *... } diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 85355389be5e..a9c05442764e 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,7 +7,7 @@ promoted[0] in FOO: &[&i32; 1] = { let mut _3: *const i32; bb0: { - _3 = const {alloc3: *const i32}; + _3 = const {ALLOC0: *const i32}; _2 = &(*_3); _1 = [move _2]; _0 = &_1; @@ -15,4 +15,4 @@ promoted[0] in FOO: &[&i32; 1] = { } } -alloc3 (extern static: X) +ALLOC0 (extern static: X) diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index ffdd195eca36..21d21b0eee0e 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -18,7 +18,7 @@ - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); -- _5 = const {alloc3: *const i32}; +- _5 = const {ALLOC0: *const i32}; - _4 = &(*_5); - _3 = [move _4]; - _2 = &_3; @@ -42,5 +42,5 @@ } } - -- alloc3 (extern static: X) +- ALLOC0 (extern static: X) diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff index c2fd7f65f5ee..5a958cc7a470 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-abort.diff @@ -26,7 +26,7 @@ } + } + -+ alloc3 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff index 21a31f9aba31..ab48186aed9a 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff @@ -26,7 +26,7 @@ } + } + -+ alloc3 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff index c0efc8730292..530cfc6539a3 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-abort.diff @@ -31,7 +31,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 03 00 │ .. } diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff index 2aee6f164aeb..08cf72e47a90 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff @@ -31,7 +31,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 03 00 │ .. } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff index d585ae89e829..b30deb2a4d43 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff @@ -39,7 +39,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 01 │ .. } diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 9fe390906380..47c51196c02a 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -39,7 +39,7 @@ } + } + -+ alloc3 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 01 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff index 18341ba7db92..6484b4b67af9 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff @@ -20,11 +20,11 @@ } + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 00 │ .. + } + -+ alloc7 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff index 50763c10f0c2..b02f04078398 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff @@ -20,11 +20,11 @@ } + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 00 00 │ .. + } + -+ alloc7 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 00 00 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff index 015180db896b..c1ef453e9df6 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff @@ -25,15 +25,15 @@ } + } + -+ alloc12 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc11 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff index 8e41705c1af2..53cdcc181672 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff @@ -25,15 +25,15 @@ } + } + -+ alloc12 (size: 2, align: 1) { ++ ALLOC0 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc11 (size: 2, align: 1) { ++ ALLOC1 (size: 2, align: 1) { + 01 02 │ .. + } + -+ alloc8 (size: 2, align: 1) { ++ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index 56a127ae31eb..c3ace9687e65 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -27,11 +27,11 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 2a 00 00 00 63 00 00 00 │ *...c... + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 2a 00 00 00 2b 00 00 00 │ *...+... } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index ac26f8ef4aef..1f74bdcfd032 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -23,7 +23,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = const {alloc1: *mut u32}; + _4 = const {ALLOC0: *mut u32}; _3 = (*_4); _1 = move _3; StorageDead(_3); @@ -39,7 +39,7 @@ } } - alloc1 (static: STATIC, size: 4, align: 4) { + ALLOC0 (static: STATIC, size: 4, align: 4) { 42 42 42 42 │ BBBB } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff index a1b433716c84..85bd2b6e722f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-abort.diff @@ -48,7 +48,7 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff index 2dc514194bc1..06e96e57a62f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff @@ -48,7 +48,7 @@ } + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index 29c455f35b35..e193c82d2c0e 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -16,12 +16,12 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = const {alloc1: &u8}; + _3 = const {ALLOC0: &u8}; - _2 = (*_3); + _2 = const 2_u8; StorageLive(_4); StorageLive(_5); - _5 = const {alloc1: &u8}; + _5 = const {ALLOC0: &u8}; - _4 = (*_5); - _1 = Add(move _2, move _4); + _4 = const 2_u8; @@ -36,7 +36,7 @@ } } - alloc1 (static: FOO, size: 1, align: 1) { + ALLOC0 (static: FOO, size: 1, align: 1) { 02 │ . } diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff index 6c9de4764658..974a42e50780 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-abort.diff @@ -19,7 +19,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff index 0f079278c43d..55dbc7002859 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff @@ -19,7 +19,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir index c2488f3944cb..f87c26bb004c 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-abort.mir @@ -15,6 +15,6 @@ fn add() -> u32 { } } -alloc5 (size: 8, align: 4) { +ALLOC0 (size: 8, align: 4) { 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir index fa0b9c77eaf6..33f97591387c 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir @@ -15,6 +15,6 @@ fn add() -> u32 { } } -alloc5 (size: 8, align: 4) { +ALLOC0 (size: 8, align: 4) { 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff index 988ef7dd2254..f19650d5a83d 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-abort.diff @@ -31,15 +31,15 @@ } + } + -+ alloc9 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc8 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc6 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff index 298446197203..67307c423310 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff @@ -31,15 +31,15 @@ } + } + -+ alloc9 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc8 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ + } + -+ alloc6 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff index b9b46f16a8b7..9bfd46231c40 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -105,15 +105,15 @@ } + } + -+ alloc11 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc10 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff index 93b18f23e61a..dba50b1428eb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -109,15 +109,15 @@ } + } + -+ alloc11 (size: 8, align: 4) { ++ ALLOC2 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc10 (size: 8, align: 4) { ++ ALLOC1 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ + } + -+ alloc7 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff index 3d3af62856bd..33fe4628d83e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -105,15 +105,15 @@ } + } + -+ alloc11 (size: 16, align: 8) { ++ ALLOC2 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc10 (size: 16, align: 8) { ++ ALLOC1 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc7 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff index 1933f9bafb36..b2d561911de5 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff @@ -87,13 +87,13 @@ + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(_3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; ++ _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -109,15 +109,15 @@ } + } + -+ alloc11 (size: 16, align: 8) { ++ ALLOC2 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc10 (size: 16, align: 8) { ++ ALLOC1 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + -+ alloc7 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 7862c23da809..1751b0de2f1b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,15 @@ } } - alloc11 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc10 (size: 8, align: 4) { + ALLOC1 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc7 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index bd4150ebb452..858a9d33ddff 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,15 @@ } } - alloc11 (size: 8, align: 4) { + ALLOC2 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc10 (size: 8, align: 4) { + ALLOC1 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } - alloc7 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 312fc7b7a82b..517070420754 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; @@ -97,15 +97,15 @@ } } - alloc11 (size: 16, align: 8) { + ALLOC2 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc10 (size: 16, align: 8) { + ALLOC1 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc7 (size: 16, align: 8) { + ALLOC0 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 3227d8b84353..9141a6c67bee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -81,11 +81,11 @@ StorageDead(_6); _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc7, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc10, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: alloc11, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; + _1 = A { foo: const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; @@ -101,15 +101,15 @@ } } - alloc11 (size: 16, align: 8) { + ALLOC2 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc10 (size: 16, align: 8) { + ALLOC1 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } - alloc7 (size: 16, align: 8) { + ALLOC0 (size: 16, align: 8) { 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index ae8b44c953e3..1348b2793308 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &E}; + _2 = const {ALLOC1: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {alloc2: &&E}; + _8 = const {ALLOC2: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - alloc2 (static: RC, size: 4, align: 4) { - ╾─alloc14─╼ │ ╾──╼ + ALLOC2 (static: RC, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } - alloc14 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - alloc1 (static: statics::C, size: 8, align: 4) { + ALLOC1 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 63799b3bac32..66929e886d3c 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -43,7 +43,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &E}; + _2 = const {ALLOC1: &E}; _1 = (*_2); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ bb4: { StorageLive(_7); StorageLive(_8); - _8 = const {alloc2: &&E}; + _8 = const {ALLOC2: &&E}; _7 = (*_8); StorageDead(_8); StorageLive(_9); @@ -112,15 +112,15 @@ } } - alloc2 (static: RC, size: 8, align: 8) { - ╾───────alloc14───────╼ │ ╾──────╼ + ALLOC2 (static: RC, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } - alloc14 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) { 01 00 00 00 04 00 00 00 │ ........ } - alloc1 (static: statics::C, size: 8, align: 4) { + ALLOC1 (static: statics::C, size: 8, align: 4) { 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 2de6ba307d58..e80f31ca9348 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {alloc1: &&BigStruct}; + _16 = const {ALLOC1: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - alloc1 (static: STAT, size: 4, align: 4) { - ╾─alloc15─╼ │ ╾──╼ + ALLOC1 (static: STAT, size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ } - alloc15 (size: 16, align: 4) { + ALLOC0 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 71a28f2165b2..de9cf1971997 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -84,7 +84,7 @@ + _10 = const S(13_i32); StorageDead(_11); StorageLive(_16); - _16 = const {alloc1: &&BigStruct}; + _16 = const {ALLOC1: &&BigStruct}; _17 = deref_copy (*_16); StorageLive(_12); _18 = deref_copy (*_16); @@ -119,11 +119,11 @@ } } - alloc1 (static: STAT, size: 8, align: 8) { - ╾───────alloc15───────╼ │ ╾──────╼ + ALLOC1 (static: STAT, size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ } - alloc15 (size: 16, align: 4) { + ALLOC0 (size: 16, align: 4) { 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index d5e58265dcc8..142e08f4d6c3 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -4,29 +4,20 @@ fn main() -> () { let mut _0: (); let _1: main::Un; - let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 2 { } - scope 3 (inlined std::mem::drop::) { - debug _x => _3; + scope 4 (inlined std::mem::drop::) { + debug _x => const 1_u32; } } + scope 3 (inlined val) { + } bb0: { StorageLive(_1); - StorageLive(_2); - _2 = val() -> [return: bb1, unwind unreachable]; - } - - bb1: { - _1 = Un { us: move _2 }; - StorageDead(_2); - StorageLive(_3); - _3 = (_1.0: u32); - StorageDead(_3); + _1 = Un { us: const 1_u32 }; StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 5eaaeba135bd..142e08f4d6c3 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -4,29 +4,20 @@ fn main() -> () { let mut _0: (); let _1: main::Un; - let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 2 { } - scope 3 (inlined std::mem::drop::) { - debug _x => _3; + scope 4 (inlined std::mem::drop::) { + debug _x => const 1_u32; } } + scope 3 (inlined val) { + } bb0: { StorageLive(_1); - StorageLive(_2); - _2 = val() -> [return: bb1, unwind continue]; - } - - bb1: { - _1 = Un { us: move _2 }; - StorageDead(_2); - StorageLive(_3); - _3 = (_1.0: u32); - StorageDead(_3); + _1 = Un { us: const 1_u32 }; StorageDead(_1); return; } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index ec5f5c1f1fc6..775a60f1c960 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc15 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 02 00 00 00 05 20 00 00 │ ..... .. } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index 9bf8637ec765..c4b57579943d 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc15 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 02 00 00 00 00 00 00 00 05 20 00 00 00 00 00 00 │ ......... ...... } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index 7dc6d21a9076..f7d0d1fb56c3 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc14 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 05 20 00 00 01 00 00 00 │ . ...... } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index 0b000876a866..15f1bd0df51a 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -66,7 +66,7 @@ } + } + -+ alloc14 (size: 16, align: 8) { ++ ALLOC0 (size: 16, align: 8) { + 05 20 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ . .............. } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff index a538756ba2d0..298a60848993 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-abort.diff @@ -7,104 +7,104 @@ debug upper => _3; let mut _0: std::result::Result<(), std::fmt::Error>; let _4: bool; - let mut _5: &std::fmt::Formatter<'_>; - let mut _7: std::option::Option; - let mut _8: &std::fmt::Formatter<'_>; - let mut _9: isize; - let mut _11: &mut std::fmt::Formatter<'_>; - let mut _12: &T; - let mut _13: core::num::flt2dec::Sign; - let mut _14: u32; - let mut _15: u32; - let mut _16: usize; - let mut _17: bool; - let mut _18: &mut std::fmt::Formatter<'_>; - let mut _19: &T; - let mut _20: core::num::flt2dec::Sign; - let mut _21: bool; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: &mut std::fmt::Formatter<'_>; + let mut _10: &T; + let mut _11: core::num::flt2dec::Sign; + let mut _12: u32; + let mut _13: u32; + let mut _14: usize; + let mut _15: bool; + let mut _16: &mut std::fmt::Formatter<'_>; + let mut _17: &T; + let mut _18: core::num::flt2dec::Sign; + let mut _19: bool; scope 1 { debug force_sign => _4; - let _6: core::num::flt2dec::Sign; + let _5: core::num::flt2dec::Sign; scope 2 { - debug sign => _6; + debug sign => _5; scope 3 { - debug precision => _10; - let _10: usize; + debug precision => _8; + let _8: usize; + scope 5 (inlined Formatter::<'_>::precision) { + debug self => _1; + } } } } + scope 4 (inlined Formatter::<'_>::sign_plus) { + debug self => _1; + let mut _20: u32; + let mut _21: u32; + } bb0: { StorageLive(_4); + StorageLive(_20); + StorageLive(_21); + _21 = ((*_1).0: u32); + _20 = BitAnd(move _21, const 1_u32); + StorageDead(_21); + _4 = Ne(move _20, const 0_u32); + StorageDead(_20); StorageLive(_5); - _5 = &(*_1); - _4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind unreachable]; + switchInt(_4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_5); - StorageLive(_6); - switchInt(_4) -> [0: bb3, otherwise: bb2]; +- _5 = MinusPlus; ++ _5 = const MinusPlus; + goto -> bb3; } bb2: { -- _6 = MinusPlus; -+ _6 = const MinusPlus; - goto -> bb4; +- _5 = Minus; ++ _5 = const Minus; + goto -> bb3; } bb3: { -- _6 = Minus; -+ _6 = const Minus; - goto -> bb4; + StorageLive(_6); + _6 = ((*_1).4: std::option::Option); + _7 = discriminant(_6); + switchInt(move _7) -> [1: bb4, otherwise: bb6]; } bb4: { - StorageLive(_7); - StorageLive(_8); - _8 = &(*_1); - _7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind unreachable]; + _8 = ((_6 as Some).0: usize); + StorageLive(_11); + _11 = _5; + StorageLive(_12); + StorageLive(_13); + _13 = _8 as u32 (IntToInt); + _12 = Add(move _13, const 1_u32); + StorageDead(_13); + _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_8); - _9 = discriminant(_7); - switchInt(move _9) -> [1: bb6, otherwise: bb8]; + StorageDead(_12); + StorageDead(_11); + goto -> bb8; } bb6: { - _10 = ((_7 as Some).0: usize); - StorageLive(_13); - _13 = _6; - StorageLive(_14); - StorageLive(_15); - _15 = _10 as u32 (IntToInt); - _14 = Add(move _15, const 1_u32); - StorageDead(_15); - _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind unreachable]; + StorageLive(_18); + _18 = _5; + _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + StorageDead(_18); + goto -> bb8; } bb8: { - StorageLive(_20); - _20 = _6; - _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> [return: bb9, unwind unreachable]; - } - - bb9: { - StorageDead(_20); - goto -> bb10; - } - - bb10: { - StorageDead(_6); + StorageDead(_5); StorageDead(_4); - StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff index 8a3dcfab44bd..037f4f7cfac2 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff @@ -7,104 +7,104 @@ debug upper => _3; let mut _0: std::result::Result<(), std::fmt::Error>; let _4: bool; - let mut _5: &std::fmt::Formatter<'_>; - let mut _7: std::option::Option; - let mut _8: &std::fmt::Formatter<'_>; - let mut _9: isize; - let mut _11: &mut std::fmt::Formatter<'_>; - let mut _12: &T; - let mut _13: core::num::flt2dec::Sign; - let mut _14: u32; - let mut _15: u32; - let mut _16: usize; - let mut _17: bool; - let mut _18: &mut std::fmt::Formatter<'_>; - let mut _19: &T; - let mut _20: core::num::flt2dec::Sign; - let mut _21: bool; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: &mut std::fmt::Formatter<'_>; + let mut _10: &T; + let mut _11: core::num::flt2dec::Sign; + let mut _12: u32; + let mut _13: u32; + let mut _14: usize; + let mut _15: bool; + let mut _16: &mut std::fmt::Formatter<'_>; + let mut _17: &T; + let mut _18: core::num::flt2dec::Sign; + let mut _19: bool; scope 1 { debug force_sign => _4; - let _6: core::num::flt2dec::Sign; + let _5: core::num::flt2dec::Sign; scope 2 { - debug sign => _6; + debug sign => _5; scope 3 { - debug precision => _10; - let _10: usize; + debug precision => _8; + let _8: usize; + scope 5 (inlined Formatter::<'_>::precision) { + debug self => _1; + } } } } + scope 4 (inlined Formatter::<'_>::sign_plus) { + debug self => _1; + let mut _20: u32; + let mut _21: u32; + } bb0: { StorageLive(_4); + StorageLive(_20); + StorageLive(_21); + _21 = ((*_1).0: u32); + _20 = BitAnd(move _21, const 1_u32); + StorageDead(_21); + _4 = Ne(move _20, const 0_u32); + StorageDead(_20); StorageLive(_5); - _5 = &(*_1); - _4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind continue]; + switchInt(_4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_5); - StorageLive(_6); - switchInt(_4) -> [0: bb3, otherwise: bb2]; +- _5 = MinusPlus; ++ _5 = const MinusPlus; + goto -> bb3; } bb2: { -- _6 = MinusPlus; -+ _6 = const MinusPlus; - goto -> bb4; +- _5 = Minus; ++ _5 = const Minus; + goto -> bb3; } bb3: { -- _6 = Minus; -+ _6 = const Minus; - goto -> bb4; + StorageLive(_6); + _6 = ((*_1).4: std::option::Option); + _7 = discriminant(_6); + switchInt(move _7) -> [1: bb4, otherwise: bb6]; } bb4: { - StorageLive(_7); - StorageLive(_8); - _8 = &(*_1); - _7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind continue]; + _8 = ((_6 as Some).0: usize); + StorageLive(_11); + _11 = _5; + StorageLive(_12); + StorageLive(_13); + _13 = _8 as u32 (IntToInt); + _12 = Add(move _13, const 1_u32); + StorageDead(_13); + _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; } bb5: { - StorageDead(_8); - _9 = discriminant(_7); - switchInt(move _9) -> [1: bb6, otherwise: bb8]; + StorageDead(_12); + StorageDead(_11); + goto -> bb8; } bb6: { - _10 = ((_7 as Some).0: usize); - StorageLive(_13); - _13 = _6; - StorageLive(_14); - StorageLive(_15); - _15 = _10 as u32 (IntToInt); - _14 = Add(move _15, const 1_u32); - StorageDead(_15); - _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind continue]; + StorageLive(_18); + _18 = _5; + _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + StorageDead(_18); + goto -> bb8; } bb8: { - StorageLive(_20); - _20 = _6; - _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> [return: bb9, unwind continue]; - } - - bb9: { - StorageDead(_20); - goto -> bb10; - } - - bb10: { - StorageDead(_6); + StorageDead(_5); StorageDead(_4); - StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs index eed1d89172ce..e442f8a7522f 100644 --- a/tests/mir-opt/inline/issue_106141.rs +++ b/tests/mir-opt/inline/issue_106141.rs @@ -3,6 +3,7 @@ pub fn outer() -> usize { inner() } +#[inline(never)] fn index() -> usize { loop {} } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff index bee01a5f97b9..b9f268df3515 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff @@ -8,31 +8,37 @@ let mut _3: &fn() {foo}; let _4: fn() {foo}; let mut _5: (); ++ scope 1 (inlined hide_foo) { ++ } bb0: { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind unreachable]; - } - - bb1: { +- _4 = hide_foo() -> [return: bb1, unwind unreachable]; +- } +- +- bb1: { _3 = &_4; StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; ++ _2 = >::call(move _3, move _5) -> [return: bb1, unwind unreachable]; } - bb2: { +- bb2: { ++ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; +- drop(_1) -> [return: bb3, unwind unreachable]; ++ drop(_1) -> [return: bb2, unwind unreachable]; } - bb3: { +- bb3: { ++ bb2: { return; } } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index 5a946712ea43..8495164df9c6 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -8,39 +8,48 @@ let mut _3: &fn() {foo}; let _4: fn() {foo}; let mut _5: (); ++ scope 1 (inlined hide_foo) { ++ } bb0: { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb4]; - } - - bb1: { +- _4 = hide_foo() -> [return: bb1, unwind: bb4]; +- } +- +- bb1: { _3 = &_4; StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; ++ _2 = >::call(move _3, move _5) -> [return: bb1, unwind: bb3]; } - bb2: { +- bb2: { ++ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind: bb5]; +- drop(_1) -> [return: bb3, unwind: bb5]; ++ drop(_1) -> [return: bb2, unwind: bb4]; } - bb3: { +- bb3: { ++ bb2: { return; } - bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate(cleanup)]; +- bb4 (cleanup): { +- drop(_1) -> [return: bb5, unwind terminate(cleanup)]; ++ bb3 (cleanup): { ++ drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } - bb5 (cleanup): { +- bb5 (cleanup): { ++ bb4 (cleanup): { resume; } } diff --git a/tests/mir-opt/inline/unit_test.rs b/tests/mir-opt/inline/unit_test.rs new file mode 100644 index 000000000000..0d877bb10b42 --- /dev/null +++ b/tests/mir-opt/inline/unit_test.rs @@ -0,0 +1,19 @@ +// Check that `-Zmir-enable-passes=+Inline` does not ICE because of stolen MIR. +// unit-test: Inline +// skip-filecheck +#![crate_type = "lib"] + +// Randomize `def_path_hash` by defining them under a module with different names +macro_rules! emit { + ($($m:ident)*) => {$( + pub mod $m { + pub fn main() { + let func = || 123u8; + func(); + } + } + )*}; +} + +// Increase the chance of triggering the bug +emit!(m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19); diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff index 28a7ffda3717..13ff1e284d9a 100644 --- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,8 +4,10 @@ fn bar() -> bool { let mut _0: bool; ++ coverage Counter(0) => /the/src/instrument_coverage.rs:20:1 - 22:2; ++ bb0: { -+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:20:1 - 22:2]; ++ Coverage::CounterIncrement(0); _0 = const true; return; } diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 9a8caa26307a..f5c59c84693f 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -7,13 +7,21 @@ let mut _2: bool; let mut _3: !; ++ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; ++ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) }; ++ coverage Counter(0) => /the/src/instrument_coverage.rs:11:1 - 11:11; ++ coverage Expression(0) => /the/src/instrument_coverage.rs:12:5 - 13:17; ++ coverage Expression(1) => /the/src/instrument_coverage.rs:14:13 - 14:18; ++ coverage Expression(1) => /the/src/instrument_coverage.rs:17:1 - 17:2; ++ coverage Counter(1) => /the/src/instrument_coverage.rs:15:10 - 15:11; ++ bb0: { -+ Coverage::Counter(0) for [/the/src/instrument_coverage.rs:11:1 - 11:11]; ++ Coverage::CounterIncrement(0); goto -> bb1; } bb1: { -+ Coverage::Expression(0) = Counter(0) + Counter(1) for [/the/src/instrument_coverage.rs:12:5 - 13:17]; ++ Coverage::ExpressionUsed(0); falseUnwind -> [real: bb2, unwind: bb6]; } @@ -27,14 +35,14 @@ } bb4: { -+ Coverage::Expression(1) = Expression(0) - Counter(1) for [/the/src/instrument_coverage.rs:14:13 - 14:18, /the/src/instrument_coverage.rs:17:1 - 17:2]; ++ Coverage::ExpressionUsed(1); _0 = const (); StorageDead(_2); return; } bb5: { -+ Coverage::Counter(1) for [/the/src/instrument_coverage.rs:15:10 - 15:11]; ++ Coverage::CounterIncrement(1); _1 = const (); StorageDead(_2); goto -> bb1; diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 132b713356ec..f8ac75513bae 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -271,6 +271,6 @@ fn main() -> () { } } -alloc4 (size: 4, align: 1) { +ALLOC0 (size: 4, align: 1) { 41 41 41 41 │ AAAA } diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 132b713356ec..f8ac75513bae 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -271,6 +271,6 @@ fn main() -> () { } } -alloc4 (size: 4, align: 1) { +ALLOC0 (size: 4, align: 1) { 41 41 41 41 │ AAAA } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff index 681e9666e0fb..bddd961c9330 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-abort.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff index db16b8d82d2c..297ebd79fad7 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff index 681e9666e0fb..bddd961c9330 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-abort.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff index db16b8d82d2c..297ebd79fad7 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff @@ -57,7 +57,7 @@ } + } + -+ alloc5 (size: 8, align: 4) { ++ ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index 1d3317efd41d..7af69e08ca1b 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26 let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13 + scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14 + debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15 + } bb0: { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 - _0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::ConstOperand - // + span: $DIR/spans.rs:10:5: 10:10 - // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } - } - - bb1: { + _0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7 StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14 return; // scope 0 at $DIR/spans.rs:11:2: 11:2 } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index aba66861f7d2..7af69e08ca1b 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -4,17 +4,14 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:9:14: 9:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:9:24: 9:26 let mut _2: &u8; // in scope 0 at $DIR/spans.rs:10:11: 10:13 + scope 1 (inlined inner) { // at $DIR/spans.rs:10:5: 10:14 + debug x => _2; // in scope 1 at $DIR/spans.rs:13:14: 13:15 + } bb0: { StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 _2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13 - _0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14 - // mir::ConstOperand - // + span: $DIR/spans.rs:10:5: 10:10 - // + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) } - } - - bb1: { + _0 = _1; // scope 1 at $DIR/spans.rs:14:5: 14:7 StorageDead(_2); // scope 0 at $DIR/spans.rs:10:13: 10:14 return; // scope 0 at $DIR/spans.rs:11:2: 11:2 } diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir index c04fdeb637d8..e6ce33ed682f 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir @@ -3,44 +3,26 @@ fn while_loop(_1: bool) -> () { debug c => _1; let mut _0: (); - let mut _2: bool; - let mut _3: bool; + scope 1 (inlined get_bool) { + debug c => _1; + } + scope 2 (inlined get_bool) { + debug c => _1; + } bb0: { goto -> bb1; } bb1: { - StorageLive(_2); - _2 = get_bool(_1) -> [return: bb2, unwind unreachable]; + switchInt(_1) -> [0: bb3, otherwise: bb2]; } bb2: { - switchInt(move _2) -> [0: bb7, otherwise: bb3]; + switchInt(_1) -> [0: bb1, otherwise: bb3]; } bb3: { - StorageLive(_3); - _3 = get_bool(_1) -> [return: bb4, unwind unreachable]; - } - - bb4: { - switchInt(move _3) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - StorageDead(_3); - StorageDead(_2); - goto -> bb1; - } - - bb6: { - StorageDead(_3); - goto -> bb7; - } - - bb7: { - StorageDead(_2); return; } } diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir index 7dc4f7ab1a87..e6ce33ed682f 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -3,44 +3,26 @@ fn while_loop(_1: bool) -> () { debug c => _1; let mut _0: (); - let mut _2: bool; - let mut _3: bool; + scope 1 (inlined get_bool) { + debug c => _1; + } + scope 2 (inlined get_bool) { + debug c => _1; + } bb0: { goto -> bb1; } bb1: { - StorageLive(_2); - _2 = get_bool(_1) -> [return: bb2, unwind continue]; + switchInt(_1) -> [0: bb3, otherwise: bb2]; } bb2: { - switchInt(move _2) -> [0: bb7, otherwise: bb3]; + switchInt(_1) -> [0: bb1, otherwise: bb3]; } bb3: { - StorageLive(_3); - _3 = get_bool(_1) -> [return: bb4, unwind continue]; - } - - bb4: { - switchInt(move _3) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - StorageDead(_3); - StorageDead(_2); - goto -> bb1; - } - - bb6: { - StorageDead(_3); - goto -> bb7; - } - - bb7: { - StorageDead(_2); return; } } diff --git a/tests/run-make/dump-ice-to-disk/check.sh b/tests/run-make/dump-ice-to-disk/check.sh index ab6f9ab60188..ff6e4be35af9 100644 --- a/tests/run-make/dump-ice-to-disk/check.sh +++ b/tests/run-make/dump-ice-to-disk/check.sh @@ -11,6 +11,12 @@ export RUSTC_ICE=$TMPDIR $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default-set.log 2>&1 default_set=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) content=$(cat $TMPDIR/rustc-ice-*.txt) +# Ensure that the ICE dump path doesn't contain `:` because they cause problems on Windows +windows_safe=$(echo rustc-ice-*.txt | grep ':') +if [ ! -z "$windows_safe" ]; then + exit 1 +fi + rm $TMPDIR/rustc-ice-*.txt RUST_BACKTRACE=short $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-short.log 2>&1 short=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) diff --git a/tests/run-make/emit-stack-sizes/foo.rs b/tests/run-make/emit-stack-sizes/foo.rs index ee51ae32886e..fd0b51205789 100644 --- a/tests/run-make/emit-stack-sizes/foo.rs +++ b/tests/run-make/emit-stack-sizes/foo.rs @@ -1,3 +1,4 @@ #![crate_type = "lib"] +#[inline(never)] pub fn foo() {} diff --git a/tests/run-make/intrinsic-unreachable/exit-ret.rs b/tests/run-make/intrinsic-unreachable/exit-ret.rs index e7b9694d9f2a..c8ba5b4599f2 100644 --- a/tests/run-make/intrinsic-unreachable/exit-ret.rs +++ b/tests/run-make/intrinsic-unreachable/exit-ret.rs @@ -2,6 +2,7 @@ use std::arch::asm; #[deny(unreachable_code)] +#[inline(never)] pub fn exit(n: usize) -> i32 { unsafe { // Pretend this asm is an exit() syscall. diff --git a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs index ec85db733df0..75f893eb2df1 100644 --- a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs +++ b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs @@ -5,6 +5,7 @@ use std::arch::asm; use std::intrinsics; #[allow(unreachable_code)] +#[inline(never)] pub fn exit(n: usize) -> i32 { unsafe { // Pretend this asm is an exit() syscall. diff --git a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs index 5c500ce6ce08..806b6d1253da 100644 --- a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs +++ b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs @@ -1,2 +1,2 @@ // check-fail -// compile-flags: --check-cfg=names() +// compile-flags: --check-cfg=cfg() diff --git a/tests/rustdoc-ui/check-cfg/check-cfg.rs b/tests/rustdoc-ui/check-cfg/check-cfg.rs index fa8789ad3ede..96fa9e08ddee 100644 --- a/tests/rustdoc-ui/check-cfg/check-cfg.rs +++ b/tests/rustdoc-ui/check-cfg/check-cfg.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options /// uniz is nor a builtin nor pass as arguments so is unexpected #[cfg(uniz)] diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.rs b/tests/rustdoc-ui/doctest/check-cfg-test.rs index 49a801c3fb35..38cd59aa790d 100644 --- a/tests/rustdoc-ui/doctest/check-cfg-test.rs +++ b/tests/rustdoc-ui/doctest/check-cfg-test.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options +// compile-flags: --test --nocapture --check-cfg=cfg(feature,values("test")) -Z unstable-options // normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR" // normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc/issue-31808.rs b/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs similarity index 67% rename from tests/rustdoc/issue-31808.rs rename to tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs index e55c5bd4f7ce..6e4709403a4d 100644 --- a/tests/rustdoc/issue-31808.rs +++ b/tests/rustdoc-ui/ice-assoc-const-for-primitive-31808.rs @@ -1,5 +1,10 @@ +// check-pass + // Test that associated item impls on primitive types don't crash rustdoc +// https://github.com/rust-lang/rust/issues/31808 +#![crate_name="issue_31808"] + pub trait Foo { const BAR: usize; type BAZ; diff --git a/tests/rustdoc/issue-29503.rs b/tests/rustdoc/blanket-impl-29503.rs similarity index 82% rename from tests/rustdoc/issue-29503.rs rename to tests/rustdoc/blanket-impl-29503.rs index 01ae4438500d..d6a132e1c263 100644 --- a/tests/rustdoc/issue-29503.rs +++ b/tests/rustdoc/blanket-impl-29503.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/29503 +#![crate_name="issue_29503"] + use std::fmt; // @has issue_29503/trait.MyTrait.html diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/const-rendering-macros-33302.rs similarity index 95% rename from tests/rustdoc/issue-33302.rs rename to tests/rustdoc/const-rendering-macros-33302.rs index a316f3ad99bc..0f5cb921411e 100644 --- a/tests/rustdoc/issue-33302.rs +++ b/tests/rustdoc/const-rendering-macros-33302.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/33302 +#![crate_name="issue_33302"] + // Ensure constant and array length values are not taken from source // code, which wreaks havoc with macros. diff --git a/tests/rustdoc/issue-32890.rs b/tests/rustdoc/disambiguate-anchors-32890.rs similarity index 80% rename from tests/rustdoc/issue-32890.rs rename to tests/rustdoc/disambiguate-anchors-32890.rs index 970954433ec7..d88601d65d38 100644 --- a/tests/rustdoc/issue-32890.rs +++ b/tests/rustdoc/disambiguate-anchors-32890.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/32890 +#![crate_name="issue_32890"] + // @has issue_32890/struct.Foo.html pub struct Foo(T); diff --git a/tests/rustdoc/issue-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs similarity index 85% rename from tests/rustdoc/issue-29449.rs rename to tests/rustdoc/disambiguate-anchors-header-29449.rs index 0d829cf6fcff..38a4954fc139 100644 --- a/tests/rustdoc/issue-29449.rs +++ b/tests/rustdoc/disambiguate-anchors-header-29449.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/29449 +#![crate_name="issue_29449"] + // @has issue_29449/struct.Foo.html pub struct Foo; diff --git a/tests/rustdoc/issue-33069.rs b/tests/rustdoc/doc-hidden-trait-implementors-33069.rs similarity index 68% rename from tests/rustdoc/issue-33069.rs rename to tests/rustdoc/doc-hidden-trait-implementors-33069.rs index 0213a53cab5d..35570668ea16 100644 --- a/tests/rustdoc/issue-33069.rs +++ b/tests/rustdoc/doc-hidden-trait-implementors-33069.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/33069 +#![crate_name="issue_33069"] + pub trait Bar {} #[doc(hidden)] diff --git a/tests/rustdoc/issue-30252.rs b/tests/rustdoc/doctest-cfg-feature-30252.rs similarity index 61% rename from tests/rustdoc/issue-30252.rs rename to tests/rustdoc/doctest-cfg-feature-30252.rs index c3777362a66d..ceb8076fe352 100644 --- a/tests/rustdoc/issue-30252.rs +++ b/tests/rustdoc/doctest-cfg-feature-30252.rs @@ -1,5 +1,8 @@ // compile-flags:--test --cfg feature="bar" +// https://github.com/rust-lang/rust/issues/30252 +#![crate_name="issue_30252"] + /// ```rust /// assert_eq!(cfg!(feature = "bar"), true); /// ``` diff --git a/tests/rustdoc/issue-32556.rs b/tests/rustdoc/doctest-ignore-32556.rs similarity index 58% rename from tests/rustdoc/issue-32556.rs rename to tests/rustdoc/doctest-ignore-32556.rs index e1cf11509972..99da9358bd6b 100644 --- a/tests/rustdoc/issue-32556.rs +++ b/tests/rustdoc/doctest-ignore-32556.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/32556 +#![crate_name="issue_32556"] + /// Blah blah blah /// ```ignore (testing rustdoc's handling of ignore) /// bad_assert!(); diff --git a/tests/rustdoc/issue-34025.rs b/tests/rustdoc/hidden-extern-34025.rs similarity index 82% rename from tests/rustdoc/issue-34025.rs rename to tests/rustdoc/hidden-extern-34025.rs index 9b9f21cb3169..81ccf2a0e5cc 100644 --- a/tests/rustdoc/issue-34025.rs +++ b/tests/rustdoc/hidden-extern-34025.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/34025 #![crate_name = "foo"] // @!has 'foo/sys/index.html' diff --git a/tests/rustdoc/issue-33592.rs b/tests/rustdoc/impl-type-parameter-33592.rs similarity index 85% rename from tests/rustdoc/issue-33592.rs rename to tests/rustdoc/impl-type-parameter-33592.rs index 7a128f0b897e..77f53710e5e7 100644 --- a/tests/rustdoc/issue-33592.rs +++ b/tests/rustdoc/impl-type-parameter-33592.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/33592 #![crate_name = "foo"] pub trait Foo {} diff --git a/tests/rustdoc/auxiliary/issue-29584.rs b/tests/rustdoc/inline_cross/auxiliary/issue-29584.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-29584.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-29584.rs diff --git a/tests/rustdoc/issue-29584.rs b/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs similarity index 68% rename from tests/rustdoc/issue-29584.rs rename to tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs index 4364a9649b57..b246e94e048d 100644 --- a/tests/rustdoc/issue-29584.rs +++ b/tests/rustdoc/inline_cross/doc-hidden-extern-trait-impl-29584.rs @@ -1,6 +1,9 @@ // aux-build:issue-29584.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/29584 +#![crate_name="issue_29584"] + extern crate issue_29584; // @has issue_29584/struct.Foo.html diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/link-extern-crate-33178.rs similarity index 85% rename from tests/rustdoc/issue-33178.rs rename to tests/rustdoc/link-extern-crate-33178.rs index ed643f5ae118..6a63712c4a78 100644 --- a/tests/rustdoc/issue-33178.rs +++ b/tests/rustdoc/link-extern-crate-33178.rs @@ -3,6 +3,9 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/33178 +#![crate_name="issue_33178"] + // @has issue_33178/index.html // @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty pub extern crate empty; diff --git a/tests/rustdoc/issue-30109.rs b/tests/rustdoc/link-extern-crate-item-30109.rs similarity index 79% rename from tests/rustdoc/issue-30109.rs rename to tests/rustdoc/link-extern-crate-item-30109.rs index e9447538ad78..c83234352ad3 100644 --- a/tests/rustdoc/issue-30109.rs +++ b/tests/rustdoc/link-extern-crate-item-30109.rs @@ -2,6 +2,9 @@ // aux-build:issue-30109-1.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/30109 +#![crate_name="issue_30109"] + pub mod quux { extern crate issue_30109_1 as bar; use self::bar::Bar; diff --git a/tests/rustdoc/issue-33178-1.rs b/tests/rustdoc/link-extern-crate-title-33178.rs similarity index 74% rename from tests/rustdoc/issue-33178-1.rs rename to tests/rustdoc/link-extern-crate-title-33178.rs index 4dc425346abb..d2f115a386e9 100644 --- a/tests/rustdoc/issue-33178-1.rs +++ b/tests/rustdoc/link-extern-crate-title-33178.rs @@ -2,6 +2,9 @@ // aux-build:variant-struct.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/33178 +#![crate_name="issue_33178_1"] + // @has issue_33178_1/index.html // @!has - //a/@title empty pub extern crate empty; diff --git a/tests/rustdoc/issue-32395.rs b/tests/rustdoc/render-enum-variant-structlike-32395.rs similarity index 81% rename from tests/rustdoc/issue-32395.rs rename to tests/rustdoc/render-enum-variant-structlike-32395.rs index 5552300f9fe8..2200d8ec6377 100644 --- a/tests/rustdoc/issue-32395.rs +++ b/tests/rustdoc/render-enum-variant-structlike-32395.rs @@ -2,6 +2,9 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/32395 +#![crate_name="issue_32395"] + // @has variant_struct/enum.Foo.html // @!hasraw - 'pub qux' // @!hasraw - 'pub(crate) qux' diff --git a/tests/rustdoc/issue-34274.rs b/tests/rustdoc/src-links-inlined-34274.rs similarity index 82% rename from tests/rustdoc/issue-34274.rs rename to tests/rustdoc/src-links-inlined-34274.rs index ce5be84a5491..a3c9bf7e45c5 100644 --- a/tests/rustdoc/issue-34274.rs +++ b/tests/rustdoc/src-links-inlined-34274.rs @@ -2,6 +2,7 @@ // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/34274 #![crate_name = "foo"] extern crate issue_34274; diff --git a/tests/rustdoc/issue-32374.rs b/tests/rustdoc/staged-api-deprecated-unstable-32374.rs similarity index 95% rename from tests/rustdoc/issue-32374.rs rename to tests/rustdoc/staged-api-deprecated-unstable-32374.rs index 985bf03a1215..d282dea907e8 100644 --- a/tests/rustdoc/issue-32374.rs +++ b/tests/rustdoc/staged-api-deprecated-unstable-32374.rs @@ -1,6 +1,8 @@ +// https://github.com/rust-lang/rust/issues/32374 #![feature(staged_api)] #![doc(issue_tracker_base_url = "https://issue_url/")] #![unstable(feature = "test", issue = "32374")] +#![crate_name="issue_32374"] // @matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \ // 'Deprecated' diff --git a/tests/rustdoc/issue-31899.rs b/tests/rustdoc/summary-codeblock-31899.rs similarity index 92% rename from tests/rustdoc/issue-31899.rs rename to tests/rustdoc/summary-codeblock-31899.rs index 3eee374465d2..c1b33058c9e7 100644 --- a/tests/rustdoc/issue-31899.rs +++ b/tests/rustdoc/summary-codeblock-31899.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/31899 +#![crate_name="issue_31899"] + // @has issue_31899/index.html // @hasraw - 'Make this line a bit longer.' // @!hasraw - 'rust rust-example-rendered' diff --git a/tests/rustdoc/issue-30366.rs b/tests/rustdoc/summary-reference-link-30366.rs similarity index 68% rename from tests/rustdoc/issue-30366.rs rename to tests/rustdoc/summary-reference-link-30366.rs index c6274a058b0e..5b9854c53903 100644 --- a/tests/rustdoc/issue-30366.rs +++ b/tests/rustdoc/summary-reference-link-30366.rs @@ -1,5 +1,8 @@ // @has issue_30366/index.html '//a/@href' 'http://www.rust-lang.org/' +// https://github.com/rust-lang/rust/issues/30366 +#![crate_name="issue_30366"] + /// Describe it. [Link somewhere][1]. /// /// [1]: http://www.rust-lang.org/ diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/type-alias-impls-32077.rs similarity index 97% rename from tests/rustdoc/issue-32077-type-alias-impls.rs rename to tests/rustdoc/type-alias-impls-32077.rs index 664b678093e9..7bb763f86afb 100644 --- a/tests/rustdoc/issue-32077-type-alias-impls.rs +++ b/tests/rustdoc/type-alias-impls-32077.rs @@ -1,5 +1,6 @@ // Regression test for . +// https://github.com/rust-lang/rust/issues/32077 #![crate_name = "foo"] pub struct GenericStruct(T); diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs new file mode 100644 index 000000000000..39980ee7c672 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs @@ -0,0 +1,13 @@ +// Test the `rustc::span_use_eq_ctxt` internal lint +// compile-flags: -Z unstable-options + +#![feature(rustc_private)] +#![deny(rustc::span_use_eq_ctxt)] +#![crate_type = "lib"] + +extern crate rustc_span; +use rustc_span::Span; + +pub fn f(s: Span, t: Span) -> bool { + s.ctxt() == t.ctxt() //~ ERROR use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` +} diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr new file mode 100644 index 000000000000..b33f62125454 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr @@ -0,0 +1,14 @@ +error: use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` + --> $DIR/span_use_eq_ctxt.rs:12:5 + | +LL | s.ctxt() == t.ctxt() + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/span_use_eq_ctxt.rs:5:9 + | +LL | #![deny(rustc::span_use_eq_ctxt)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui-fulldeps/stable-mir/instance.rs b/tests/ui-fulldeps/stable-mir/instance.rs new file mode 100644 index 000000000000..fe06d9b5cc96 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/instance.rs @@ -0,0 +1,91 @@ +// run-pass +// Test that users are able to use stable mir APIs to retrieve monomorphized instances + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_middle; +extern crate rustc_smir; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; + +use stable_mir::*; +use rustc_smir::rustc_internal; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let items = stable_mir::all_local_items(); + + // Get all items and split generic vs monomorphic items. + let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| { + item.requires_monomorphization() + }); + assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant"); + assert_eq!(generic.len(), 2, "Expected 2 generic functions"); + + // For all monomorphic items, get the correspondent instances. + let instances = mono.iter().filter_map(|item| { + mir::mono::Instance::try_from(*item).ok() + }).collect::>(); + assert_eq!(instances.len(), mono.len()); + + // For all generic items, try_from should fail. + assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err())); + + ControlFlow::Continue(()) +} + + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "instance_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + rustc_internal::StableMir::new(args, test_stable_mir).run().unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn ty_param(t: &T) -> T where T: Clone {{ + t.clone() + }} + + pub fn const_param(a: [bool; LEN]) -> bool {{ + LEN > 0 && a[0] + }} + + pub fn monomorphic() {{ + }} + + pub mod foo {{ + pub fn bar_mono(i: i32) -> i64 {{ + i as i64 + }} + }} + "# + )?; + Ok(()) +} diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr index 5435f22321c9..e39224f2c164 100644 --- a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -14,14 +14,12 @@ note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` | LL | const ID: i32 = 3; | ^^^^^^^^^^^^^ -help: disambiguate the associated constant for candidate #1 - | -LL | const X: i32 = ::ID; - | ~~~~~~~~~~~~~~ -help: disambiguate the associated constant for candidate #2 +help: use fully-qualified syntax to disambiguate | LL | const X: i32 = ::ID; | ~~~~~~~~~~~~~~ +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index 6f206f2b89c7..866a53f57fc2 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -33,7 +33,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-109071.rs:15:22 | LL | fn T() -> Option {} - | ^^^^^^^^^^ help: use the fully-qualified path: ` as IntoIterator>::Item` + | ^^^^^^^^^^ help: use fully-qualified syntax: ` as IntoIterator>::Item` error: aborting due to 4 previous errors diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr index 88c72042ce2d..9206b4f6db7e 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:12 | LL | let _: S::::Pr = (); - | ^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Tr>::Pr` + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Tr>::Pr` error: aborting due to previous error diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr index 97088b79fd67..f7a47be8dc39 100644 --- a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/ambiguous-associated-type-with-generics.rs:13:13 | LL | let _x: >::Ty; - | ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Assoc>::Ty` + | ^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Assoc>::Ty` error: aborting due to previous error diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr index d0c170620766..a2346e292ac4 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-item-duplicate-names-3.rs:18:12 | LL | let x: Baz::Bar = 5; - | ^^^^^^^^ help: use the fully-qualified path: `::Bar` + | ^^^^^^^^ help: use fully-qualified syntax: `::Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr index cc10bbcc0b50..a29e32a784fe 100644 --- a/tests/ui/associated-type-bounds/elision.stderr +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -17,7 +17,7 @@ LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> | ----------------------------- -------------- ^^^^^^^^ expected `Option<&()>`, found `Option>` | | | | | expected `Option<&()>` because of return type - | this type parameter + | found this type parameter | = note: expected enum `Option<&()>` found enum `Option>` diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed new file mode 100644 index 000000000000..b9f26a40219b --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed @@ -0,0 +1,14 @@ +// run-rustfix +trait O { + type M; +} +trait U { + const N: A::M; +} +impl O for D { + type M = u8; +} +impl> U for u16 { + const N: C::M = 4u8; //~ ERROR mismatched types +} +fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs new file mode 100644 index 000000000000..abff6af73e24 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs @@ -0,0 +1,14 @@ +// run-rustfix +trait O { + type M; +} +trait U { + const N: A::M; +} +impl O for D { + type M = u8; +} +impl U for u16 { + const N: C::M = 4u8; //~ ERROR mismatched types +} +fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr new file mode 100644 index 000000000000..b104f38ce908 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 + | +LL | const N: C::M = 4u8; + | ^^^ expected associated type, found `u8` + | + = note: expected associated type `::M` + found type `u8` +help: consider constraining the associated type `::M` to `u8` + | +LL | impl> U for u16 { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr index 236552baf928..df01e1e37686 100644 --- a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr +++ b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr @@ -10,11 +10,11 @@ LL | type Color; LL | fn a(_: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn a(_: ::Color) { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn a(_: ::Color) { | ~~~~~~~~~~~~~~~~ @@ -31,11 +31,11 @@ LL | type Color; LL | fn b(_: C::Color) where C : Vehicle+Box { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { | ~~~~~~~~~~~~~~~~ @@ -52,11 +52,11 @@ LL | type Color; LL | fn c(_: C::Color) where C : Vehicle, C : Box { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { | ~~~~~~~~~~~~~~~~ @@ -73,11 +73,11 @@ LL | type Color; LL | fn e(&self, _: X::Color) where X : Box; | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; | ~~~~~~~~~~~~~~~~ @@ -94,11 +94,11 @@ LL | type Color; LL | fn f(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~~~~~ @@ -115,11 +115,11 @@ LL | type Color; LL | fn d(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index e765f9323984..4f8954b80bc7 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -18,11 +18,11 @@ LL | type Color; LL | fn dent(c: C, color: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { | ~~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { | ~~~~~~~~~~~~ @@ -71,11 +71,11 @@ LL | type Color; LL | fn paint(c: C, d: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { | ~~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { | ~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index 1ff6fd4b821e..d361643f024d 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:22:17 | LL | trait Foo where Foo::Assoc: Bar { - | ^^^^^^^^^^ help: use the fully-qualified path: `::Assoc` + | ^^^^^^^^^^ help: use fully-qualified syntax: `::Assoc` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:27:10 @@ -21,7 +21,7 @@ error[E0223]: ambiguous associated type LL | type X = std::ops::Deref::Target; | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: use the fully-qualified path +help: use fully-qualified syntax | LL | type X = ::Target; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -37,7 +37,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:13:23 | LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use the fully-qualified path: `::Value` + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:16:22 diff --git a/tests/ui/associated-types/associated-types-issue-20346.stderr b/tests/ui/associated-types/associated-types-issue-20346.stderr index b1708b96e525..f384079862fb 100644 --- a/tests/ui/associated-types/associated-types-issue-20346.stderr +++ b/tests/ui/associated-types/associated-types-issue-20346.stderr @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == Option< --> $DIR/associated-types-issue-20346.rs:34:36 | LL | fn test_adapter>>(it: I) { - | - this type parameter + | - found this type parameter ... LL | is_iterator_of::, _>(&adapter); | ------------------------------ ^^^^^^^^ type mismatch resolving ` as Iterator>::Item == Option` diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr index a67f77e37c70..cab9dcec0b6b 100644 --- a/tests/ui/associated-types/associated-types-path-1.stderr +++ b/tests/ui/associated-types/associated-types-path-1.stderr @@ -16,11 +16,11 @@ LL | type A; LL | pub fn f2(a: T, x: T::A) {} | ^^^^ ambiguous associated type `A` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} | ~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} | ~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index dd0389c34e69..425cfdca01d1 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -2,7 +2,9 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | | + | expected this type parameter | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.rs b/tests/ui/async-await/in-trait/unconstrained-impl-region.rs new file mode 100644 index 000000000000..c06f9f005f19 --- /dev/null +++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.rs @@ -0,0 +1,19 @@ +// edition: 2021 + +pub(crate) trait Inbox { + async fn next(self) -> M; +} + +pub(crate) trait Actor: Sized { + type Message; + + async fn on_mount(self, _: impl Inbox); +} + +impl<'a> Actor for () { +//~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + type Message = &'a (); + async fn on_mount(self, _: impl Inbox<&'a ()>) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr new file mode 100644 index 000000000000..2cb0da2e8bc0 --- /dev/null +++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/unconstrained-impl-region.rs:13:6 + | +LL | impl<'a> Actor for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/check-cfg/allow-at-crate-level.rs b/tests/ui/check-cfg/allow-at-crate-level.rs index ce3383a2961a..1629d2e0b673 100644 --- a/tests/ui/check-cfg/allow-at-crate-level.rs +++ b/tests/ui/check-cfg/allow-at-crate-level.rs @@ -1,7 +1,7 @@ // This test check that #![allow(unexpected_cfgs)] works with --cfg // // check-pass -// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options +// compile-flags: --cfg=unexpected --check-cfg=cfg() -Z unstable-options #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-macro-cfg.rs b/tests/ui/check-cfg/allow-macro-cfg.rs index 8016a4d190cc..ea26355aca8f 100644 --- a/tests/ui/check-cfg/allow-macro-cfg.rs +++ b/tests/ui/check-cfg/allow-macro-cfg.rs @@ -1,7 +1,7 @@ // This test check that local #[allow(unexpected_cfgs)] works // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] fn foo() { diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs index 6c869dc42023..29491e0b39e2 100644 --- a/tests/ui/check-cfg/allow-same-level.rs +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -1,7 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] #[cfg(FALSE)] diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs index d14b0eae5ccd..df06f655d9af 100644 --- a/tests/ui/check-cfg/allow-top-level.rs +++ b/tests/ui/check-cfg/allow-top-level.rs @@ -1,7 +1,7 @@ // This test check that a top-level #![allow(unexpected_cfgs)] works // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs index 04340694d9c1..bd5c97815f2d 100644 --- a/tests/ui/check-cfg/allow-upper-level.rs +++ b/tests/ui/check-cfg/allow-upper-level.rs @@ -1,7 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] work if put on an upper level // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[allow(unexpected_cfgs)] mod aa { diff --git a/tests/ui/check-cfg/compact-names.rs b/tests/ui/check-cfg/compact-names.rs index bff807400396..4f7168255cf3 100644 --- a/tests/ui/check-cfg/compact-names.rs +++ b/tests/ui/check-cfg/compact-names.rs @@ -1,7 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs index 1f17057840cc..13c072fe9206 100644 --- a/tests/ui/check-cfg/compact-values.rs +++ b/tests/ui/check-cfg/compact-values.rs @@ -1,7 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // // check-pass -// compile-flags:--check-cfg=values() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs new file mode 100644 index 000000000000..0f9178ce6a57 --- /dev/null +++ b/tests/ui/check-cfg/concat-values.rs @@ -0,0 +1,13 @@ +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar")) + +#[cfg(my_cfg)] +//~^ WARNING unexpected `cfg` condition value +fn my_cfg() {} + +#[cfg(my_cfg = "unk")] +//~^ WARNING unexpected `cfg` condition value +fn my_cfg() {} + +fn main() {} diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr new file mode 100644 index 000000000000..da2bd7d6ad92 --- /dev/null +++ b/tests/ui/check-cfg/concat-values.stderr @@ -0,0 +1,19 @@ +warning: unexpected `cfg` condition value: (none) + --> $DIR/concat-values.rs:5:7 + | +LL | #[cfg(my_cfg)] + | ^^^^^^ + | + = note: expected values for `my_cfg` are: `bar`, `foo` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/concat-values.rs:9:7 + | +LL | #[cfg(my_cfg = "unk")] + | ^^^^^^^^^^^^^^ + | + = note: expected values for `my_cfg` are: `bar`, `foo` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs index 49e127d079a7..45875bddc176 100644 --- a/tests/ui/check-cfg/diagnotics.rs +++ b/tests/ui/check-cfg/diagnotics.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --check-cfg=values(no_values) -Z unstable-options +// compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values) -Z unstable-options #[cfg(featur)] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/empty-names.rs b/tests/ui/check-cfg/empty-names.rs deleted file mode 100644 index 046ff0364e27..000000000000 --- a/tests/ui/check-cfg/empty-names.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Check warning for unexpected cfg -// -// check-pass -// compile-flags: --check-cfg=names() -Z unstable-options - -#[cfg(unknown_key = "value")] -//~^ WARNING unexpected `cfg` condition name -pub fn f() {} - -fn main() {} diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs deleted file mode 100644 index 9bda42e5d15f..000000000000 --- a/tests/ui/check-cfg/empty-values.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Check warning for unexpected cfg value -// -// check-pass -// compile-flags: --check-cfg=values() -Z unstable-options - -#[cfg(test = "value")] -//~^ WARNING unexpected `cfg` condition value -pub fn f() {} - -fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr new file mode 100644 index 000000000000..53ccc0f4d317 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `empty_cfg` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr new file mode 100644 index 000000000000..5e8b74054ceb --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `empty_names_values` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr new file mode 100644 index 000000000000..7705a665eb77 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -0,0 +1,33 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/exhaustive-names-values.rs:20:7 + | +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `std` + +warning: unexpected condition value `` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: 4 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr new file mode 100644 index 000000000000..f0224a2e33c7 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -0,0 +1,33 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names-values.rs:12:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-names-values.rs:16:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `cfg` condition value: `unk` + --> $DIR/exhaustive-names-values.rs:20:7 + | +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `std` + +warning: unexpected `full` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 4 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs new file mode 100644 index 000000000000..f553d93cae2a --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names-values.rs @@ -0,0 +1,34 @@ +// Check warning for unexpected cfg in the code and in the CLI +// arguments (here the revision cfg). +// +// check-pass +// revisions: empty_names_values empty_cfg feature full +// compile-flags: -Z unstable-options +// [empty_names_values]compile-flags: --check-cfg=names() --check-cfg=values() +// [empty_cfg]compile-flags: --check-cfg=cfg() +// [feature]compile-flags: --check-cfg=cfg(feature,values("std")) +// [full]compile-flags: --check-cfg=cfg(feature,values("std")) --check-cfg=cfg() + +#[cfg(unknown_key = "value")] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +#[cfg(test = "value")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +#[cfg(feature = "unk")] +//[feature]~^ WARNING unexpected `cfg` condition value +//[full]~^^ WARNING unexpected `cfg` condition value +pub fn feat() {} + +#[cfg(feature = "std")] +pub fn feat() {} + +#[cfg(windows)] +pub fn win() {} + +#[cfg(unix)] +pub fn unix() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-names.stderr b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr similarity index 76% rename from tests/ui/check-cfg/empty-names.stderr rename to tests/ui/check-cfg/exhaustive-names.empty_names.stderr index 9bba852c6def..6190ff71464c 100644 --- a/tests/ui/check-cfg/empty-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/empty-names.rs:6:7 + --> $DIR/exhaustive-names.rs:8:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,9 @@ LL | #[cfg(unknown_key = "value")] = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default -warning: 1 warning emitted +warning: unexpected `empty_names` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr new file mode 100644 index 000000000000..f338434cd299 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr @@ -0,0 +1,15 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names.rs:8:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `exhaustive_names` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/exhaustive-names.rs b/tests/ui/check-cfg/exhaustive-names.rs new file mode 100644 index 000000000000..b86a7f84eb4b --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names.rs @@ -0,0 +1,12 @@ +// Check warning for unexpected cfg +// +// check-pass +// revisions: empty_names exhaustive_names +// [empty_names]compile-flags: --check-cfg=names() -Z unstable-options +// [exhaustive_names]compile-flags: --check-cfg=cfg() -Z unstable-options + +#[cfg(unknown_key = "value")] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr new file mode 100644 index 000000000000..999b27028497 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr @@ -0,0 +1,17 @@ +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-values.rs:9:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `empty_cfg` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/exhaustive-values.empty_values.stderr similarity index 88% rename from tests/ui/check-cfg/empty-values.stderr rename to tests/ui/check-cfg/exhaustive-values.empty_values.stderr index 932651c5bfe1..77ddc35100ae 100644 --- a/tests/ui/check-cfg/empty-values.stderr +++ b/tests/ui/check-cfg/exhaustive-values.empty_values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/empty-values.rs:6:7 + --> $DIR/exhaustive-values.rs:9:7 | LL | #[cfg(test = "value")] | ^^^^---------- diff --git a/tests/ui/check-cfg/exhaustive-values.rs b/tests/ui/check-cfg/exhaustive-values.rs new file mode 100644 index 000000000000..8a1689ba86b5 --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.rs @@ -0,0 +1,13 @@ +// Check warning for unexpected cfg value +// +// check-pass +// revisions: empty_values empty_cfg without_names +// [empty_values]compile-flags: --check-cfg=values() -Z unstable-options +// [empty_cfg]compile-flags: --check-cfg=cfg() -Z unstable-options +// [without_names]compile-flags: --check-cfg=cfg(any()) -Z unstable-options + +#[cfg(test = "value")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr new file mode 100644 index 000000000000..77ddc35100ae --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition value: `value` + --> $DIR/exhaustive-values.rs:9:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr index 850924d993ac..925664bb3fc6 100644 --- a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr +++ b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr @@ -1,2 +1,2 @@ -error: invalid `--check-cfg` argument: `anything_else(...)` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`) +error: invalid `--check-cfg` argument: `anything_else(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) diff --git a/tests/ui/check-cfg/invalid-arguments.giberich.stderr b/tests/ui/check-cfg/invalid-arguments.giberich.stderr new file mode 100644 index 000000000000..d427033fcc26 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.giberich.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) + diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr new file mode 100644 index 000000000000..0dc44d9ac76c --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr new file mode 100644 index 000000000000..d0a1453e3c40 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr new file mode 100644 index 000000000000..9239f8cce945 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names) + diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr new file mode 100644 index 000000000000..4c406143d080 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` (`values()` arguments cannot specify string literals and `any()` at the same time) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr new file mode 100644 index 000000000000..6f1db1b13c31 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr new file mode 100644 index 000000000000..bce305b09c30 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr new file mode 100644 index 000000000000..748ce231af73 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times) + diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr new file mode 100644 index 000000000000..daf38147fe53 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty) + diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr new file mode 100644 index 000000000000..79f83e802ca5 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty) + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index 5090ce3e845d..79bef89c9574 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -2,9 +2,33 @@ // // check-fail // revisions: anything_else names_simple_ident values_simple_ident values_string_literals -// [anything_else]compile-flags: -Z unstable-options --check-cfg=anything_else(...) -// [names_simple_ident]compile-flags: -Z unstable-options --check-cfg=names("NOT_IDENT") -// [values_simple_ident]compile-flags: -Z unstable-options --check-cfg=values("NOT_IDENT") -// [values_string_literals]compile-flags: -Z unstable-options --check-cfg=values(test,12) +// revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values +// revisions: multiple_values_any not_empty_any not_empty_values_any +// revisions: values_any_missing_values values_any_before_ident ident_in_values_1 +// revisions: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3 +// revisions: mixed_values_any mixed_any giberich +// +// compile-flags: -Z unstable-options +// [anything_else]compile-flags: --check-cfg=anything_else(...) +// [names_simple_ident]compile-flags: --check-cfg=names("NOT_IDENT") +// [values_simple_ident]compile-flags: --check-cfg=values("NOT_IDENT") +// [values_string_literals]compile-flags: --check-cfg=values(test,12) +// [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") +// [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) +// [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) +// [multiple_values]compile-flags: --check-cfg=cfg(foo,values(),values()) +// [multiple_values_any]compile-flags: --check-cfg=cfg(foo,values(any(),any())) +// [not_empty_any]compile-flags: --check-cfg=cfg(any(foo)) +// [not_empty_values_any]compile-flags: --check-cfg=cfg(foo,values(any(bar))) +// [values_any_missing_values]compile-flags: --check-cfg=cfg(foo,any()) +// [values_any_before_ident]compile-flags: --check-cfg=cfg(values(any()),foo) +// [ident_in_values_1]compile-flags: --check-cfg=cfg(foo,values(bar)) +// [ident_in_values_2]compile-flags: --check-cfg=cfg(foo,values("bar",bar,"bar")) +// [unknown_meta_item_1]compile-flags: --check-cfg=abc() +// [unknown_meta_item_2]compile-flags: --check-cfg=cfg(foo,test()) +// [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test())) +// [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any())) +// [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any())) +// [giberich]compile-flags: --check-cfg=cfg(...) fn main() {} diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr new file mode 100644 index 000000000000..c6f6834ffd30 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr new file mode 100644 index 000000000000..ab3dc86cd1ad --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr new file mode 100644 index 000000000000..c04b15ec265c --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr new file mode 100644 index 000000000000..cee65f9887b9 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr new file mode 100644 index 000000000000..2441e2537b74 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals or `any()`) + diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr new file mode 100644 index 000000000000..fc93ec8fbdfd --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names) + diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr new file mode 100644 index 000000000000..f41672fcbdb6 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation) + diff --git a/tests/ui/check-cfg/invalid-cfg-name.rs b/tests/ui/check-cfg/invalid-cfg-name.rs deleted file mode 100644 index 8499d3d4448d..000000000000 --- a/tests/ui/check-cfg/invalid-cfg-name.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Check warning for invalid configuration name -// -// edition:2018 -// check-pass -// compile-flags: --check-cfg=names() -Z unstable-options - -#[cfg(widnows)] -//~^ WARNING unexpected `cfg` condition name -pub fn f() {} - -#[cfg(windows)] -pub fn g() {} - -pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-value.rs b/tests/ui/check-cfg/invalid-cfg-value.rs deleted file mode 100644 index 9e428d367fdf..000000000000 --- a/tests/ui/check-cfg/invalid-cfg-value.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Check warning for invalid configuration value -// -// edition:2018 -// check-pass -// compile-flags: --check-cfg=values(feature,"serde","full") --cfg=feature="rand" -Z unstable-options - -#[cfg(feature = "sedre")] -//~^ WARNING unexpected `cfg` condition value -pub fn f() {} - -#[cfg(feature = "serde")] -pub fn g() {} - -#[cfg(feature = "rand")] -//~^ WARNING unexpected `cfg` condition value -pub fn h() {} - -pub fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.cfg.stderr similarity index 81% rename from tests/ui/check-cfg/mix.stderr rename to tests/ui/check-cfg/mix.cfg.stderr index 23da9f22a72c..daa200440cc9 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:11:7 + --> $DIR/mix.rs:15:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` @@ -7,7 +7,7 @@ LL | #[cfg(widnows)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/mix.rs:15:7 + --> $DIR/mix.rs:19:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "foo"` @@ -15,7 +15,7 @@ LL | #[cfg(feature)] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:22:7 + --> $DIR/mix.rs:26:7 | LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(feature = "bar")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:26:7 + --> $DIR/mix.rs:30:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ @@ -31,12 +31,12 @@ LL | #[cfg(feature = "zebra")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `uu` - --> $DIR/mix.rs:30:12 + --> $DIR/mix.rs:34:12 | LL | #[cfg_attr(uu, test)] | ^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` warning: unexpected condition value `bar` for condition name `feature` | @@ -47,13 +47,13 @@ warning: unexpected `unknown_name` as condition name = help: was set with `--cfg` but isn't in the `--check-cfg` expected names warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:39:10 + --> $DIR/mix.rs:43:10 | LL | cfg!(widnows); | ^^^^^^^ help: there is a config with a similar name: `windows` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:42:10 + --> $DIR/mix.rs:46:10 | LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | cfg!(feature = "bar"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:44:10 + --> $DIR/mix.rs:48:10 | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ @@ -69,25 +69,25 @@ LL | cfg!(feature = "zebra"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:46:10 + --> $DIR/mix.rs:50:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:48:10 + --> $DIR/mix.rs:52:10 | LL | cfg!(xxx); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:50:14 + --> $DIR/mix.rs:54:14 | LL | cfg!(any(xxx, windows)); | ^^^ warning: unexpected `cfg` condition value: `bad` - --> $DIR/mix.rs:52:14 + --> $DIR/mix.rs:56:14 | LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ @@ -95,43 +95,43 @@ LL | cfg!(any(feature = "bad", windows)); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:54:23 + --> $DIR/mix.rs:58:23 | LL | cfg!(any(windows, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:56:20 + --> $DIR/mix.rs:60:20 | LL | cfg!(all(unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:58:14 + --> $DIR/mix.rs:62:14 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:58:18 + --> $DIR/mix.rs:62:18 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:61:14 + --> $DIR/mix.rs:65:14 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:61:18 + --> $DIR/mix.rs:65:18 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:64:20 + --> $DIR/mix.rs:68:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -139,13 +139,13 @@ LL | cfg!(any(unix, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:66:14 + --> $DIR/mix.rs:70:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:66:19 + --> $DIR/mix.rs:70:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -153,19 +153,19 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:69:14 + --> $DIR/mix.rs:73:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:69:25 + --> $DIR/mix.rs:73:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:14 + --> $DIR/mix.rs:76:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:33 + --> $DIR/mix.rs:76:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:72:52 + --> $DIR/mix.rs:76:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/mix.names_values.stderr b/tests/ui/check-cfg/mix.names_values.stderr new file mode 100644 index 000000000000..daa200440cc9 --- /dev/null +++ b/tests/ui/check-cfg/mix.names_values.stderr @@ -0,0 +1,192 @@ +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/mix.rs:15:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: there is a config with a similar name: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: (none) + --> $DIR/mix.rs:19:7 + | +LL | #[cfg(feature)] + | ^^^^^^^- help: specify a config value: `= "foo"` + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/mix.rs:26:7 + | +LL | #[cfg(feature = "bar")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:30:7 + | +LL | #[cfg(feature = "zebra")] + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `uu` + --> $DIR/mix.rs:34:12 + | +LL | #[cfg_attr(uu, test)] + | ^^ + | + = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + +warning: unexpected condition value `bar` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: unexpected `unknown_name` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/mix.rs:43:10 + | +LL | cfg!(widnows); + | ^^^^^^^ help: there is a config with a similar name: `windows` + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/mix.rs:46:10 + | +LL | cfg!(feature = "bar"); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:48:10 + | +LL | cfg!(feature = "zebra"); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:50:10 + | +LL | cfg!(xxx = "foo"); + | ^^^^^^^^^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:52:10 + | +LL | cfg!(xxx); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:54:14 + | +LL | cfg!(any(xxx, windows)); + | ^^^ + +warning: unexpected `cfg` condition value: `bad` + --> $DIR/mix.rs:56:14 + | +LL | cfg!(any(feature = "bad", windows)); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:58:23 + | +LL | cfg!(any(windows, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:60:20 + | +LL | cfg!(all(unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `aa` + --> $DIR/mix.rs:62:14 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `bb` + --> $DIR/mix.rs:62:18 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `aa` + --> $DIR/mix.rs:65:14 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name: `bb` + --> $DIR/mix.rs:65:18 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:68:20 + | +LL | cfg!(any(unix, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:70:14 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:70:19 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:73:14 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name: `xxx` + --> $DIR/mix.rs:73:25 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:14 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:33 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:76:52 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `foo` + +warning: 28 warnings emitted + diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index 9adf5c46e43f..d7b3b4953b7a 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -3,7 +3,11 @@ // we correctly lint on the `cfg!` macro and `cfg_attr` attribute. // // check-pass -// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options +// revisions: names_values cfg +// compile-flags: --cfg feature="bar" --cfg unknown_name -Z unstable-options +// compile-flags: --check-cfg=cfg(names_values,cfg) +// [names_values]compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") +// [cfg]compile-flags: --check-cfg=cfg(feature,values("foo")) #[cfg(windows)] fn do_windows_stuff() {} diff --git a/tests/ui/check-cfg/no-values.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr similarity index 86% rename from tests/ui/check-cfg/no-values.stderr rename to tests/ui/check-cfg/no-expected-values.empty.stderr index b05a569dd01c..5d261b2a5e63 100644 --- a/tests/ui/check-cfg/no-values.stderr +++ b/tests/ui/check-cfg/no-expected-values.empty.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-values.rs:6:7 + --> $DIR/no-expected-values.rs:12:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-values.rs:10:7 + --> $DIR/no-expected-values.rs:16:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs new file mode 100644 index 000000000000..9e2a9f09aedc --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.rs @@ -0,0 +1,20 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// revisions: values simple mixed empty +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(values,simple,mixed,empty) +// [values]compile-flags: --check-cfg=values(test) --check-cfg=values(feature) +// [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature) +// [mixed]compile-flags: --check-cfg=cfg(test,feature) +// [empty]compile-flags: --check-cfg=cfg(test,feature,values()) + +#[cfg(feature = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +#[cfg(test = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.simple.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-expected-values.values.stderr b/tests/ui/check-cfg/no-expected-values.values.stderr new file mode 100644 index 000000000000..5d261b2a5e63 --- /dev/null +++ b/tests/ui/check-cfg/no-expected-values.values.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:12:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `foo` + --> $DIR/no-expected-values.rs:16:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/no-values.rs b/tests/ui/check-cfg/no-values.rs deleted file mode 100644 index 8c80f56cb5a3..000000000000 --- a/tests/ui/check-cfg/no-values.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Check that we detect unexpected value when none are allowed -// -// check-pass -// compile-flags: --check-cfg=values(test) --check-cfg=values(feature) -Z unstable-options - -#[cfg(feature = "foo")] -//~^ WARNING unexpected `cfg` condition value -fn do_foo() {} - -#[cfg(test = "foo")] -//~^ WARNING unexpected `cfg` condition value -fn do_foo() {} - -fn main() {} diff --git a/tests/ui/check-cfg/stmt-no-ice.rs b/tests/ui/check-cfg/stmt-no-ice.rs index cf76487ed46f..383e830a1b22 100644 --- a/tests/ui/check-cfg/stmt-no-ice.rs +++ b/tests/ui/check-cfg/stmt-no-ice.rs @@ -1,7 +1,7 @@ // This test checks that there is no ICE with this code // // check-pass -// compile-flags:--check-cfg=names() -Z unstable-options +// compile-flags:--check-cfg=cfg() -Z unstable-options fn main() { #[cfg(crossbeam_loom)] diff --git a/tests/ui/check-cfg/invalid-cfg-name.stderr b/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr similarity index 86% rename from tests/ui/check-cfg/invalid-cfg-name.stderr rename to tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr index 8c3c72c96671..513f7ac7fd18 100644 --- a/tests/ui/check-cfg/invalid-cfg-name.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/invalid-cfg-name.rs:7:7 + --> $DIR/unexpected-cfg-name.rs:9:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` diff --git a/tests/ui/check-cfg/unexpected-cfg-name.names.stderr b/tests/ui/check-cfg/unexpected-cfg-name.names.stderr new file mode 100644 index 000000000000..513f7ac7fd18 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-name.names.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name: `widnows` + --> $DIR/unexpected-cfg-name.rs:9:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: there is a config with a similar name: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/unexpected-cfg-name.rs b/tests/ui/check-cfg/unexpected-cfg-name.rs new file mode 100644 index 000000000000..15c3aa6e0812 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-name.rs @@ -0,0 +1,16 @@ +// Check warning for unexpected configuration name +// +// check-pass +// revisions: names exhaustive +// compile-flags: --check-cfg=cfg(names,exhaustive) +// [names]compile-flags: --check-cfg=names() -Z unstable-options +// [exhaustive]compile-flags: --check-cfg=cfg() -Z unstable-options + +#[cfg(widnows)] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +#[cfg(windows)] +pub fn g() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr similarity index 89% rename from tests/ui/check-cfg/invalid-cfg-value.stderr rename to tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr index 947beac6ffd6..2ed7f9005573 100644 --- a/tests/ui/check-cfg/invalid-cfg-value.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `sedre` - --> $DIR/invalid-cfg-value.rs:7:7 + --> $DIR/unexpected-cfg-value.rs:11:7 | LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "sedre")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `rand` - --> $DIR/invalid-cfg-value.rs:14:7 + --> $DIR/unexpected-cfg-value.rs:18:7 | LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/unexpected-cfg-value.rs b/tests/ui/check-cfg/unexpected-cfg-value.rs new file mode 100644 index 000000000000..a84458071de8 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-value.rs @@ -0,0 +1,22 @@ +// Check warning for invalid configuration value in the code and +// in the cli +// +// check-pass +// revisions: values cfg +// compile-flags: --cfg=feature="rand" -Z unstable-options +// compile-flags: --check-cfg=cfg(values,cfg) +// [values]compile-flags: --check-cfg=values(feature,"serde","full") +// [cfg]compile-flags: --check-cfg=cfg(feature,values("serde","full")) + +#[cfg(feature = "sedre")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +#[cfg(feature = "serde")] +pub fn g() {} + +#[cfg(feature = "rand")] +//~^ WARNING unexpected `cfg` condition value +pub fn h() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/unexpected-cfg-value.values.stderr b/tests/ui/check-cfg/unexpected-cfg-value.values.stderr new file mode 100644 index 000000000000..2ed7f9005573 --- /dev/null +++ b/tests/ui/check-cfg/unexpected-cfg-value.values.stderr @@ -0,0 +1,25 @@ +warning: unexpected `cfg` condition value: `sedre` + --> $DIR/unexpected-cfg-value.rs:11:7 + | +LL | #[cfg(feature = "sedre")] + | ^^^^^^^^^^------- + | | + | help: there is a expected value with a similar name: `"serde"` + | + = note: expected values for `feature` are: `full`, `serde` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `rand` + --> $DIR/unexpected-cfg-value.rs:18:7 + | +LL | #[cfg(feature = "rand")] + | ^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: `full`, `serde` + +warning: unexpected condition value `rand` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/unknown-values.rs b/tests/ui/check-cfg/unknown-values.rs new file mode 100644 index 000000000000..c082a2f25ace --- /dev/null +++ b/tests/ui/check-cfg/unknown-values.rs @@ -0,0 +1,17 @@ +// Check that no warning is emitted for unknown cfg value +// +// check-pass +// revisions: simple mixed with_values +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(simple,mixed,with_values) +// [simple]compile-flags: --check-cfg=cfg(foo,values(any())) +// [mixed]compile-flags: --check-cfg=cfg(foo) --check-cfg=cfg(foo,values(any())) +// [with_values]compile-flags:--check-cfg=cfg(foo,values(any())) --check-cfg=cfg(foo,values("aa")) + +#[cfg(foo = "value")] +pub fn f() {} + +#[cfg(foo)] +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs index e57fb69a1e05..1dcb419b4a73 100644 --- a/tests/ui/check-cfg/well-known-names.rs +++ b/tests/ui/check-cfg/well-known-names.rs @@ -1,7 +1,7 @@ // This test checks that we lint on non well known names and that we don't lint on well known names // // check-pass -// compile-flags: --check-cfg=names() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(target_oz = "linux")] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index a5d38a99eeec..3001289b7e06 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -2,11 +2,13 @@ warning: unexpected `cfg` condition name: `target_oz` --> $DIR/well-known-names.rs:6:7 | LL | #[cfg(target_oz = "linux")] - | ---------^^^^^^^^^^ - | | - | help: there is a config with a similar name: `target_os` + | ^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unexpected_cfgs)]` on by default +help: there is a config with a similar name and value + | +LL | #[cfg(target_os = "linux")] + | ~~~~~~~~~ warning: unexpected `cfg` condition name: `features` --> $DIR/well-known-names.rs:13:7 diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 96375dc8d313..8b56c8729d84 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -2,7 +2,7 @@ // values // // check-pass -// compile-flags: --check-cfg=values() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(target_os = "linuz")] //~^ WARNING unexpected `cfg` condition value diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index ecc73d994f9a..4f32639a6310 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -24,3 +24,28 @@ LL | #![deny(coinductive_overlap_in_coherence)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: implementations of `PartialEq>` for `Interval<_>` will conflict in the future + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1 + | +LL | #[derive(PartialEq, Default)] + | --------- the second impl is here +... +LL | / impl PartialEq for Interval +LL | | +LL | | +LL | | where +LL | | T: Borrow, +LL | | Q: ?Sized + PartialOrd, + | |___________________________^ the first impl is here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #114040 + = note: impls that are not considered to overlap may be considered to overlap in the future + = note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap +note: the lint level is defined here + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9 + | +LL | #![deny(coinductive_overlap_in_coherence)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index 796966b22d51..5832dbe1777d 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -11,7 +11,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-100313.rs:10:13 | LL | *(B as *const bool as *mut bool) = false; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to ALLOC0 which is read-only | note: inside `T::<&true>::set_false` --> $DIR/issue-100313.rs:10:13 diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr index 8879aec35e59..ee17ec3c698b 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-67945-1.rs:10:20 | LL | struct Bug { - | - this type parameter + | - expected this type parameter ... LL | let x: S = MaybeUninit::uninit(); | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found `MaybeUninit<_>` diff --git a/tests/ui/const-ptr/forbidden_slices.rs b/tests/ui/const-ptr/forbidden_slices.rs index 93e3bb09ff15..03d6499aefbb 100644 --- a/tests/ui/const-ptr/forbidden_slices.rs +++ b/tests/ui/const-ptr/forbidden_slices.rs @@ -1,7 +1,7 @@ // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" -// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" + #![feature( slice_from_ptr_range, const_slice_from_ptr_range, diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index 4ae0ffff63d5..00230d59a371 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -122,7 +122,7 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC10 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -181,7 +181,7 @@ LL | pub static R7: &[u16] = unsafe { error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC11 has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds | note: inside `ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index bfdd5859719b..be75f76b26f2 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -14,7 +14,7 @@ LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -29,7 +29,7 @@ LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr index 54fafded07ba..d8971eb9969f 100644 --- a/tests/ui/consts/const-compare-bytes-ub.stderr +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -20,25 +20,25 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:22:9 | LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc6 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:26:9 | LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc13 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:30:9 | LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc17[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:34:9 | LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc25[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:38:9 diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index a0f4519eaad3..82de91effe73 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc2──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index d2bffa42561a..de23aafe05cc 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc2────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr index 032dcad86a49..5f4630f6f4bc 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -8,7 +8,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_dangling.rs:18:5 | LL | *reference - | ^^^^^^^^^^ memory access failed: alloc4 has been freed, so this pointer is dangling + | ^^^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr index 0884ade45a7e..916344a7b816 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_duplicate.rs:9:5 | LL | intrinsics::const_deallocate(ptr, 4, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc2 has been freed, so this pointer is dangling + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr index 4c23957a1f80..4b1f0f686ca0 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr @@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:8:5 | LL | intrinsics::const_deallocate(ptr, 4, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc2 has size 4 and alignment 4, but gave size 4 and alignment 2 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC0 has size 4 and alignment 4, but gave size 4 and alignment 2 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:13:5 | LL | intrinsics::const_deallocate(ptr, 2, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc4 has size 4 and alignment 4, but gave size 2 and alignment 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC1 has size 4 and alignment 4, but gave size 2 and alignment 4 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:19:5 | LL | intrinsics::const_deallocate(ptr, 3, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc6 has size 4 and alignment 4, but gave size 3 and alignment 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC2 has size 4 and alignment 4, but gave size 3 and alignment 4 error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5 diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index 1f9b1dfe31e5..2022a16e789e 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-49296.rs:9:16 | LL | const X: u64 = *wat(42); - | ^^^^^^^^ memory access failed: alloc3 has been freed, so this pointer is dangling + | ^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr index 13ca4379b7bd..b948e07b92db 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/partial_ptr_overwrite.rs:8:9 | LL | *(ptr as *mut u8) = 123; - | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at ALLOC0 | = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 042e7eeb31e1..689ebf752236 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -211,7 +211,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:106:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index 8426a95055cc..3447a8ab432c 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -211,7 +211,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:106:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -385,7 +385,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:175:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -396,7 +396,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:179:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -418,7 +418,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -451,7 +451,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index 6c1238c0a063..e005922223ad 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -1,8 +1,8 @@ // stderr-per-bitwidth // ignore-endian-big // ignore-tidy-linelength -// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼" -// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$1╼" + #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)] #![allow(invalid_value)] diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 2d09b5494c68..9b79a0a7d347 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,8 +1,8 @@ -// normalize-stderr-test "alloc\d+" -> "allocN" #![feature(const_pointer_byte_offsets)] #![feature(pointer_byte_offsets)] #![feature(const_mut_refs)] + const MISALIGNED_LOAD: () = unsafe { let mem = [0u32; 8]; let ptr = mem.as_ptr().byte_add(1); diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr index 663d49f21b44..f644e5f87481 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr +++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr @@ -35,7 +35,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/raw-pointer-ub.rs:43:16 | LL | let _val = *ptr; - | ^^^^ memory access failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | ^^^^ memory access failed: ALLOC0 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds error: aborting due to 5 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 13c5920bd37b..7b30233c0256 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN──╼ ╾─allocN──╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──╼╾──╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index ba47865bcf96..9330ae3c9a6b 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN────────╼ ╾───────allocN────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs index 7fb58f43bcb9..7d1927253f22 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -11,7 +11,7 @@ // errors are emitted instead of ICEs. // stderr-per-bitwidth -// normalize-stderr-test "alloc\d+" -> "allocN" + trait Trait {} diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs index a64b3a74cf6c..fe4ec4d23d05 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.rs +++ b/tests/ui/consts/const-eval/ub-nonnull.rs @@ -1,6 +1,6 @@ // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature(rustc_attrs, ptr_metadata)] #![allow(invalid_value)] // make sure we cannot allow away the errors tested here diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 2df76f2c9e2c..7822306b654c 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/ub-nonnull.rs:20:29 | LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^^ out-of-bounds pointer arithmetic: alloc11 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC1 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:24:1 diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs index a5d2ea014865..08d4dce4d17f 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.rs +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(invalid_value)] use std::mem; diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index 2144d1471082..c608bad2a47b 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -141,7 +141,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:59:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc39, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr index f7898e55ee2c..353a9b782240 100644 --- a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc3──╼ ╾─alloc4──╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr index 60432380e134..097f6b049dc8 100644 --- a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index 02cf5326c6a1..dc8d4c640c2f 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -5,11 +5,11 @@ use std::mem; // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" // normalize-stderr-test "offset \d+" -> "offset N" -// normalize-stderr-test "alloc\d+" -> "allocN" // normalize-stderr-test "size \d+" -> "size N" + /// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error /// message. #[repr(transparent)] diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index d57e4720c918..b203794858ac 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -189,7 +189,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC12, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -200,7 +200,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC14, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -222,7 +222,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:124:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -233,7 +233,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -244,7 +244,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:130:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -255,7 +255,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:133:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -288,7 +288,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:145:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -310,7 +310,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:154:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-points-to-static.32bit.stderr b/tests/ui/consts/const-points-to-static.32bit.stderr index c7a435a1ee3f..12cc7fbb1fc6 100644 --- a/tests/ui/consts/const-points-to-static.32bit.stderr +++ b/tests/ui/consts/const-points-to-static.32bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/const-points-to-static.64bit.stderr b/tests/ui/consts/const-points-to-static.64bit.stderr index 4d5b8eac541d..86506e6ca010 100644 --- a/tests/ui/consts/const-points-to-static.64bit.stderr +++ b/tests/ui/consts/const-points-to-static.64bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr index be41c2db398b..0e4e6a6ad6c4 100644 --- a/tests/ui/consts/copy-intrinsic.stderr +++ b/tests/ui/consts/copy-intrinsic.stderr @@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:27:5 | LL | copy_nonoverlapping(0x100 as *const i32, dangle, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer at offset 40 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 4, so pointer at offset 40 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:34:5 | LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc7 has size 4, so pointer at offset 40 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 4, so pointer at offset 40 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/copy-intrinsic.rs:41:5 diff --git a/tests/ui/consts/effect_param.rs b/tests/ui/consts/effect_param.rs new file mode 100644 index 000000000000..f11ec739fce5 --- /dev/null +++ b/tests/ui/consts/effect_param.rs @@ -0,0 +1,11 @@ +//! Ensure we don't allow accessing const effect parameters from stable Rust. + +fn main() { + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied +} + +const FOO: () = { + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied +}; diff --git a/tests/ui/consts/effect_param.stderr b/tests/ui/consts/effect_param.stderr new file mode 100644 index 000000000000..f8c4bfc02e54 --- /dev/null +++ b/tests/ui/consts/effect_param.stderr @@ -0,0 +1,19 @@ +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:9:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^--------- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:4:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^-------- help: remove these generics + | | + | expected 0 generic arguments + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index 0c57751cbfa4..32b67a13061c 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc7──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 6c4d5882158d..45f999eb23c2 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc7────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } note: erroneous constant encountered diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr index 755c7fb7d4d9..5375ec1188a5 100644 --- a/tests/ui/consts/issue-63952.32bit.stderr +++ b/tests/ui/consts/issue-63952.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc4──╼ ff ff ff ff │ ╾──╼.... + ╾ALLOC0╼ ff ff ff ff │ ╾──╼.... } error: aborting due to previous error diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr index abdb9a4f7920..a6edbf9321b9 100644 --- a/tests/ui/consts/issue-63952.64bit.stderr +++ b/tests/ui/consts/issue-63952.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc4────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + ╾ALLOC0╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ } error: aborting due to previous error diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr index b8798a9755fe..af59729d438d 100644 --- a/tests/ui/consts/issue-79690.64bit.stderr +++ b/tests/ui/consts/issue-79690.64bit.stderr @@ -6,7 +6,7 @@ LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr index a6f467b9ef48..4a3344a5b045 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc4──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc5──╼ │ ╾──╼ + ╾ALLOC1╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr index cfaf31a6e0c4..7573bfa39ec2 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc4────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc5────────╼ │ ╾──────╼ + ╾ALLOC1╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index e3a0d93f09b7..de59d743b17d 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index a323e9a05f09..e62520ef6ad2 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 0ea1792409b8..c9da91a95977 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc3──╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc7──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ + ╾ALLOC1╼ ╾ALLOC2╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc10─╼ │ ╾──╼ + ╾ALLOC3╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 67959d25634a..71be616b7ed7 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -6,7 +6,7 @@ LL | const MUH: Meh = Meh { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc3────────╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ + ╾ALLOC1╼ ╾ALLOC2╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc10───────╼ │ ╾──────╼ + ╾ALLOC3╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index dd2b81c5af2b..1ac3777f5feb 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,5 +1,5 @@ // compile-flags: -Z ui-testing=no -// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID" + #![feature(const_swap)] #![feature(const_mut_refs)] diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index fcfb9fbb3f8c..6860cee4184f 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | - = note: unable to copy parts of a pointer from memory at ALLOC_ID + = note: unable to copy parts of a pointer from memory at ALLOC0 | note: inside `std::ptr::read::>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 97ff6efdd791..1ef727e5b0f3 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -39,19 +39,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:53:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC0 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:62:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC1 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:70:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc23 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC2 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:79:14 diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs index 1b01e4fd1473..db28a6c6a2b4 100644 --- a/tests/ui/consts/offset_ub.rs +++ b/tests/ui/consts/offset_ub.rs @@ -1,6 +1,6 @@ use std::ptr; -// normalize-stderr-test "alloc\d+" -> "allocN" + // normalize-stderr-test "0x7f+" -> "0x7f..f" diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index c0c851df5076..8bc59d50ee4b 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -14,7 +14,7 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -27,7 +27,7 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC1 has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -92,7 +92,7 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC2 has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -105,7 +105,7 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: ALLOC3 has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index efa6bb668240..5c0c7a0b94ff 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -191,7 +191,7 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:39:19 diff --git a/tests/ui/error-codes/E0034.stderr b/tests/ui/error-codes/E0034.stderr index e29621702657..da6f221881ce 100644 --- a/tests/ui/error-codes/E0034.stderr +++ b/tests/ui/error-codes/E0034.stderr @@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Tes | LL | fn foo() {} | ^^^^^^^^ -help: disambiguate the associated function for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo() | ~~~~~~~~~~~~~~~~~~ -help: disambiguate the associated function for candidate #2 - | LL | ::foo() | ~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr index 5414d77ad7c5..e600acf78344 100644 --- a/tests/ui/error-codes/E0221.stderr +++ b/tests/ui/error-codes/E0221.stderr @@ -10,11 +10,11 @@ LL | fn do_something() { LL | let _: Self::A; | ^^^^^^^ ambiguous associated type `A` | -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::A; | ~~~~~~~~~~~~~~~ -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::A; | ~~~~~~~~~~~~~~~ @@ -29,7 +29,7 @@ LL | let _: Self::Err; | ^^^^^^^^^ ambiguous associated type `Err` | = note: associated type `Self` could derive from `FromStr` -help: use fully qualified syntax to disambiguate +help: use fully-qualified syntax to disambiguate | LL | let _: ::Err; | ~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr index 42945e42f6ea..1299ba5f50c1 100644 --- a/tests/ui/error-codes/E0223.stderr +++ b/tests/ui/error-codes/E0223.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/E0223.rs:8:14 | LL | let foo: MyTrait::X; - | ^^^^^^^^^^ help: use the fully-qualified path: `::X` + | ^^^^^^^^^^ help: use fully-qualified syntax: `::X` error: aborting due to previous error diff --git a/tests/ui/generic-associated-types/issue-68648-2.stderr b/tests/ui/generic-associated-types/issue-68648-2.stderr index b2bef19eb5e9..0514e7bd6f69 100644 --- a/tests/ui/generic-associated-types/issue-68648-2.stderr +++ b/tests/ui/generic-associated-types/issue-68648-2.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-68648-2.rs:12:17 | LL | fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { - | - this type parameter + | - expected this type parameter LL | T::identity(()) | ----------- ^^ expected type parameter `T`, found `()` | | diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr index f0212e985a92..20c07db4c04f 100644 --- a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/issue-68656-unsized-values.rs:13:21 | LL | impl UnsafeCopy for T { - | - this type parameter + | - expected this type parameter LL | type Item<'a> = T; | ^ expected type parameter `T`, found associated type | diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 520aeff18948..ad40ee180019 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-88360.rs:15:9 | LL | trait SuperTrait - | - this type parameter + | - found this type parameter ... LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { | ------------- expected `&T` because of return type diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 535edec575a7..1d7d80d1b076 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:11:11 | LL | impl Add for A where B: Add { - | - this type parameter + | - expected this type parameter ... LL | A(self.0 + rhs.0) | - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type @@ -44,7 +44,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:21:14 | LL | impl Add for C { - | - this type parameter + | - expected this type parameter ... LL | Self(self.0 + rhs.0) | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type @@ -80,7 +80,7 @@ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:42:14 | LL | impl Add for E where ::Output = B { - | - this type parameter + | - expected this type parameter ... LL | Self(self.0 + rhs.0) | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5ed0d9fcf1ef..1fd61084130a 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr index 40446a3d339a..d5086c7bc515 100644 --- a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr +++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr @@ -7,7 +7,7 @@ LL | | &mut Header, LL | | &mut [EntryMetadata], LL | | &mut [Entry] LL | | ) -> R, - | |__________- this type parameter + | |__________- expected this type parameter LL | ) { LL | let () = y; | ^^ - this expression has type `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry]) -> R` diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr new file mode 100644 index 000000000000..83791f0d3afd --- /dev/null +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -0,0 +1,29 @@ +error: internal compiler error: no errors encountered even though `delay_span_bug` issued + +error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }} + | + = + + +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }))), bound_vars: [] } } } + --> $DIR/equality-in-canonical-query.rs:19:5 + | +LL | same_output(foo, rpit); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + + --> $DIR/equality-in-canonical-query.rs:19:5 + | +LL | same_output(foo, rpit); + | ^^^^^^^^^^^^^^^^^^^^^^ + + + + + + + +query stack during panic: +end of query stack +error: aborting due to 3 previous errors + diff --git a/tests/ui/impl-trait/equality-in-canonical-query.rs b/tests/ui/impl-trait/equality-in-canonical-query.rs new file mode 100644 index 000000000000..672b1eeeab69 --- /dev/null +++ b/tests/ui/impl-trait/equality-in-canonical-query.rs @@ -0,0 +1,23 @@ +// issue: #116877 +// revisions: sized clone +//[sized] check-pass + +//[clone] known-bug: #108498 +//[clone] failure-status: 101 +//[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" +//[clone] normalize-stderr-test: "(?m)note: .*$" -> "" +//[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" +//[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> "" + +#[cfg(sized)] fn rpit() -> impl Sized {} +#[cfg(clone)] fn rpit() -> impl Clone {} + +fn same_output(_: impl Fn() -> Out, _: impl Fn() -> Out) {} + +pub fn foo() -> impl Sized { + same_output(rpit, foo); + same_output(foo, rpit); + rpit() +} + +fn main () {} diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 59139e4d5ae6..874a1b95a431 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -6,7 +6,7 @@ LL | fn early<'late, T>(_: &'late ()) {} | | | | | expected type parameter `T`, found `()` | | help: change the parameter type to match the trait: `&T` - | this type parameter + | expected this type parameter | note: type in trait --> $DIR/method-signature-matches.rs:52:28 diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr index 1d169b5d690c..25c0adeddbd7 100644 --- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr +++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr @@ -2,7 +2,7 @@ error[E0053]: method `bar` has an incompatible type for trait --> $DIR/specialization-broken.rs:15:22 | LL | default impl Foo for U - | - this type parameter + | - found this type parameter ... LL | fn bar(&self) -> U { | ^ diff --git a/tests/ui/impl-trait/universal-mismatched-type.stderr b/tests/ui/impl-trait/universal-mismatched-type.stderr index a56e542d8345..82e0f23964f7 100644 --- a/tests/ui/impl-trait/universal-mismatched-type.stderr +++ b/tests/ui/impl-trait/universal-mismatched-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn foo(x: impl Debug) -> String { | ---------- ------ expected `String` because of return type | | - | this type parameter + | found this type parameter LL | x | ^ expected `String`, found type parameter `impl Debug` | diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr index 6233b629ad6c..55825f7765bb 100644 --- a/tests/ui/inference/issue-107090.stderr +++ b/tests/ui/inference/issue-107090.stderr @@ -70,7 +70,7 @@ error[E0308]: mismatched types --> $DIR/issue-107090.rs:22:5 | LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { - | - this type parameter ------- expected `&'out T` because of return type + | - expected this type parameter ------- expected `&'out T` because of return type LL | LL | sadness.cast() | ^^^^^^^^^^^^^^ expected `&T`, found `&Foo<'_, '_, T>` diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 4fc304cda604..317466eb3226 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:5:5 | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5 diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr index b1c15672051d..b34aa8e1ff5a 100644 --- a/tests/ui/issues/issue-20225.stderr +++ b/tests/ui/issues/issue-20225.stderr @@ -2,7 +2,7 @@ error[E0053]: method `call` has an incompatible type for trait --> $DIR/issue-20225.rs:6:43 | LL | impl<'a, T> Fn<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | ^^^^ | | @@ -16,7 +16,7 @@ error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:11:51 | LL | impl<'a, T> FnMut<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | ^^^^ | | @@ -30,7 +30,7 @@ error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:18:47 | LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { - | - this type parameter + | - found this type parameter ... LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | ^^^^ diff --git a/tests/ui/issues/issue-51154.stderr b/tests/ui/issues/issue-51154.stderr index 002d5ccdc67a..5ae8e067807f 100644 --- a/tests/ui/issues/issue-51154.stderr +++ b/tests/ui/issues/issue-51154.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-51154.rs:2:30 | LL | fn foo() { - | - this type parameter + | - expected this type parameter LL | let _: Box = Box::new(|| ()); | -------- ^^^^^ expected type parameter `F`, found closure | | diff --git a/tests/ui/issues/issue-69306.stderr b/tests/ui/issues/issue-69306.stderr index 570677298ffa..6fc5c33af6ac 100644 --- a/tests/ui/issues/issue-69306.stderr +++ b/tests/ui/issues/issue-69306.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:5:28 | LL | impl S0 { - | - this type parameter + | - expected this type parameter LL | const C: S0 = Self(0); | ---- ^ expected type parameter `T`, found integer | | @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:5:23 | LL | impl S0 { - | - this type parameter + | - found this type parameter LL | const C: S0 = Self(0); | ^^^^^^^ expected `S0`, found `S0` | @@ -31,7 +31,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:10:14 | LL | impl S0 { - | - this type parameter + | - expected this type parameter ... LL | Self(0); | ---- ^ expected type parameter `T`, found integer @@ -50,7 +50,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:27:14 | LL | impl Foo for as Fun>::Out { - | - this type parameter + | - expected this type parameter LL | fn foo() { LL | Self(0); | ---- ^ expected type parameter `T`, found integer @@ -69,7 +69,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:33:32 | LL | impl S1 { - | - this type parameter + | - expected this type parameter LL | const C: S1 = Self(0, 1); | ---- ^ expected type parameter `T`, found integer | | @@ -87,7 +87,7 @@ error[E0308]: mismatched types --> $DIR/issue-69306.rs:33:27 | LL | impl S1 { - | - this type parameter + | - found this type parameter LL | const C: S1 = Self(0, 1); | ^^^^^^^^^^ expected `S1`, found `S1` | diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.fixed b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed new file mode 100644 index 000000000000..513b5bd13d83 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.fixed @@ -0,0 +1,42 @@ +// run-rustfix +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x }) + .map(|x| { x }) + .sum::(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1 + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.rs b/tests/ui/iterators/invalid-iterator-chain-fixable.rs new file mode 100644 index 000000000000..79b861702c78 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.rs @@ -0,0 +1,42 @@ +// run-rustfix +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let v = vec![(0, 0)]; + let scores = v + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| { x; }) + .map(|x| { x }) + .sum::(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 + println!("{g:?}"); + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr new file mode 100644 index 000000000000..1bfe765e78af --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr @@ -0,0 +1,157 @@ +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain-fixable.rs:7:7 + | +LL | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` +LL | i.collect() + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&X>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `X`, found `&X` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:5:26 + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + | ^^^^^^^^^^^ `Iterator::Item` is `&X` here +LL | let i = i.map(|x| x.clone()); + | ------------------ `Iterator::Item` remains `&X` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + | ++++++++++++++ + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:17:33 + | +LL | println!("{}", scores.sum::()); + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:14:10 + | +LL | let v = vec![(0, 0)]; + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | let scores = v +LL | .iter() + | ------ `Iterator::Item` is `&({integer}, {integer})` here +LL | .map(|(a, b)| { + | __________^ +LL | | a + b; +LL | | }); + | |__________^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:25:20 + | +LL | .sum::(), + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:23:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| { x; }) + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here +LL | .map(|x| { x }) + | -------------- `Iterator::Item` remains `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:27:60 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | --- ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + + > +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:27:38 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here + | | | + | | `Iterator::Item` is `&{integer}` here + | this expression has type `Vec<{integer}>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); + | + +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain-fixable.rs:36:25 + | +LL | let g: Vec = f.collect(); + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` + = help: for that trait implementation, expected `i32`, found `()` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-fixable.rs:32:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ----------- `Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- `Iterator::Item` remains `{integer}` here +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- `Iterator::Item` remains `{integer}` here +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ `Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- `Iterator::Item` remains `()` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index 2601c9c0d69d..4dc130869123 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -1,6 +1,8 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` --> $DIR/invalid-iterator-chain.rs:6:7 | +LL | let i = i.map(|x| x.clone()); + | ------- this method call is cloning the reference `&X`, not `X` which doesn't implement `Clone` LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | @@ -16,6 +18,10 @@ LL | let i = i.map(|x| x.clone()); | ------------------ `Iterator::Item` remains `&X` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider further restricting type parameter `X` + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec where X: Clone { + | ++++++++++++++ error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:15:33 @@ -43,6 +49,11 @@ LL | | }); | |__________^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - a + b; +LL + a + b + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` --> $DIR/invalid-iterator-chain.rs:26:20 @@ -77,6 +88,11 @@ LL | .map(|x| { x; }) | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - .map(|x| { x; }) +LL + .map(|x| { x }) + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` --> $DIR/invalid-iterator-chain.rs:36:20 @@ -130,6 +146,11 @@ LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); | this expression has type `Vec<{integer}>` note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); +LL + println!("{}", vec![0, 1].iter().map(|x| { x }).sum::()); + | error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` --> $DIR/invalid-iterator-chain.rs:39:46 @@ -182,6 +203,11 @@ LL | let f = e.filter(|_| false); | ----------------- `Iterator::Item` remains `()` here note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider removing this semicolon + | +LL - x + 1; +LL + x + 1 + | error: aborting due to 7 previous errors diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr index 4582b69850cf..25570f960537 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -4,7 +4,7 @@ error[E0308]: lang item `start` function has wrong type LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { | - ^^^^^^^^^^^ expected type parameter `T`, found `u16` | | - | this type parameter + | expected this type parameter | = note: expected signature `fn(fn() -> T, _, _, _) -> _` found signature `fn(fn() -> u16, _, _, _) -> _` diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index a19f4963c239..01ca08a6f19b 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type --> $DIR/bare-trait-objects-path.rs:23:12 | LL | let _: Dyn::Ty; - | ^^^^^^^ help: use the fully-qualified path: `::Ty` + | ^^^^^^^ help: use fully-qualified syntax: `::Ty` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bare-trait-objects-path.rs:14:5 diff --git a/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs b/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs new file mode 100644 index 000000000000..2d5e90720ef2 --- /dev/null +++ b/tests/ui/lint/missing-copy-implementations-non-exhaustive.rs @@ -0,0 +1,25 @@ +// Test for issue #116766. +// Ensure that we don't suggest impl'ing `Copy` for a type if it or at least one +// of it's variants are marked as `non_exhaustive`. + +// check-pass + +#![deny(missing_copy_implementations)] + +#[non_exhaustive] +pub enum MyEnum { + A, +} + +#[non_exhaustive] +pub struct MyStruct { + foo: usize, +} + +pub enum MyEnum2 { + #[non_exhaustive] + A, + B, +} + +fn main() {} diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs new file mode 100644 index 000000000000..6a17f6a2172a --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -0,0 +1,38 @@ +trait A { + type Type; + const CONST: usize; + fn foo(&self); +} + +trait B { + type Type; + const CONST: usize; + fn foo(&self); +} + +#[derive(Debug)] +struct S; + +impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP use fully-qualified syntax to disambiguate + S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP use fully-qualified syntax to disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use fully-qualified syntax +} diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr new file mode 100644 index 000000000000..a9e9c679fdb6 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -0,0 +1,63 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-blanket-impl.rs:36:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:30:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:19:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:25:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | ::foo(&s); + | ~~~~~~~~~~ +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 + | +LL | S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:18:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:24:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | ::CONST; + | ~~~~~~~~~~ +LL | ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs new file mode 100644 index 000000000000..9a82ff01574a --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -0,0 +1,37 @@ +trait A { + type Type; + const CONST: usize; + fn foo(&self); +} + +trait B { + type Type; + const CONST: usize; + fn foo(&self); +} + +struct S; + +impl A for S { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for S { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP use fully-qualified syntax + let _: S::Type = (); //~ ERROR ambiguous associated type + //~| HELP use fully-qualified syntax + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP use fully-qualified syntax +} diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr new file mode 100644 index 000000000000..901bfc30a3f2 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -0,0 +1,63 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-impl.rs:32:12 + | +LL | let _: S::Type = (); + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:29:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:18:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:24:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | ::foo(&s); + | ~~~~~~~~~~ +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:34:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:17:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:23:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.rs b/tests/ui/methods/disambiguate-multiple-trait-2.rs new file mode 100644 index 000000000000..829491d824d7 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.rs @@ -0,0 +1,54 @@ +trait A { + type Type; //~ NOTE ambiguous `Type` from `A` + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self); //~ NOTE candidate #1 +} + +trait B { + type Type; //~ NOTE ambiguous `Type` from `B` + const CONST: usize; //~ NOTE candidate #2 + fn foo(&self); //~ NOTE candidate #2 +} + +trait C: A + B {} + +fn a(t: T) { + t.foo(); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate the method + //~| HELP disambiguate the method + let _ = T::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP use fully-qualified syntax + let _: T::Type; //~ ERROR ambiguous associated type + //~^ NOTE ambiguous associated type `Type` + //~| HELP use fully-qualified syntax + //~| HELP use fully-qualified syntax +} + +#[derive(Debug)] +struct S; + +impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP use fully-qualified syntax + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP use fully-qualified syntax + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use fully-qualified syntax +} diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr new file mode 100644 index 000000000000..0f9c60ce243d --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -0,0 +1,132 @@ +error[E0221]: ambiguous associated type `Type` in bounds of `T` + --> $DIR/disambiguate-multiple-trait-2.rs:23:12 + | +LL | type Type; + | --------- ambiguous `Type` from `A` +... +LL | type Type; + | --------- ambiguous `Type` from `B` +... +LL | let _: T::Type; + | ^^^^^^^ ambiguous associated type `Type` + | +help: use fully-qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ +help: use fully-qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:16:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:4:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:10:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | A::foo(t); + | ~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | B::foo(t); + | ~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:20:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:3:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:9:5 + | +LL | const CONST: usize; + | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | let _ = A::CONST; + | ~~~ +LL | let _ = B::CONST; + | ~~~ + +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait-2.rs:52:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:46:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:35:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:41:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | ::foo(&s); + | ~~~~~~~~~~ +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:49:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:34:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:40:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0034, E0221, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait.rs b/tests/ui/methods/disambiguate-multiple-trait.rs new file mode 100644 index 000000000000..c990d047576b --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.rs @@ -0,0 +1,32 @@ +#![feature(associated_type_defaults)] + +trait A { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +trait B { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +#[derive(Debug)] +struct S; + +impl A for T {} + +impl B for T {} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP use fully-qualified syntax + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP use fully-qualified syntax + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use fully-qualified syntax +} diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr new file mode 100644 index 000000000000..9a50d51245ba --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -0,0 +1,63 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait.rs:30:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use fully-qualified syntax + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:24:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:6:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:12:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | ::foo(&s); + | ~~~~~~~~~~ +LL | ::foo(&s); + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:27:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:5:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:11:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr index 4ba778e0ef72..5bb887b4503a 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `AB` | LL | fn foo() {} | ^^^^^^^^ -help: disambiguate the associated function for candidate #1 +help: use fully-qualified syntax to disambiguate | LL | ::foo(); | ~~~~~~~~~~~ -help: disambiguate the associated function for candidate #2 - | LL | ::foo(); | ~~~~~~~~~~~ diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index de4e067fead4..881ff909722f 100644 --- a/tests/ui/mismatched_types/issue-35030.stderr +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-35030.rs:9:14 | LL | impl Parser for bool { - | ---- this type parameter + | ---- expected this type parameter LL | fn parse(text: &str) -> Option { LL | Some(true) | ---- ^^^^ expected type parameter `bool`, found `bool` diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.rs b/tests/ui/repr/explicit-rust-repr-conflicts.rs new file mode 100644 index 000000000000..22dd12d316ac --- /dev/null +++ b/tests/ui/repr/explicit-rust-repr-conflicts.rs @@ -0,0 +1,23 @@ +#[repr(C, Rust)] //~ ERROR conflicting representation hints +struct S { + a: i32, +} + + +#[repr(Rust)] //~ ERROR conflicting representation hints +#[repr(C)] +struct T { + a: i32, +} + +#[repr(Rust, u64)] //~ ERROR conflicting representation hints +enum U { + V, +} + +#[repr(Rust, simd)] +//~^ ERROR conflicting representation hints +//~| ERROR SIMD types are experimental and possibly buggy +struct F32x4(f32, f32, f32, f32); + +fn main() {} diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.stderr b/tests/ui/repr/explicit-rust-repr-conflicts.stderr new file mode 100644 index 000000000000..7126da574b63 --- /dev/null +++ b/tests/ui/repr/explicit-rust-repr-conflicts.stderr @@ -0,0 +1,39 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/explicit-rust-repr-conflicts.rs:18:1 + | +LL | #[repr(Rust, simd)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:1:8 + | +LL | #[repr(C, Rust)] + | ^ ^^^^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:7:8 + | +LL | #[repr(Rust)] + | ^^^^ +LL | #[repr(C)] + | ^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:13:8 + | +LL | #[repr(Rust, u64)] + | ^^^^ ^^^ + +error[E0566]: conflicting representation hints + --> $DIR/explicit-rust-repr-conflicts.rs:18:8 + | +LL | #[repr(Rust, simd)] + | ^^^^ ^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0566, E0658. +For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/return/return-impl-trait-bad.stderr b/tests/ui/return/return-impl-trait-bad.stderr index 237b85ee66a1..a015b9f53aff 100644 --- a/tests/ui/return/return-impl-trait-bad.stderr +++ b/tests/ui/return/return-impl-trait-bad.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn bad_echo(_t: T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | "this should not suggest impl Trait" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` | @@ -17,7 +17,7 @@ error[E0308]: mismatched types LL | fn bad_echo_2(_t: T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | "this will not suggest it, because that would probably be wrong" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` | @@ -30,7 +30,7 @@ error[E0308]: mismatched types LL | fn other_bounds_bad() -> T | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter ... LL | "don't suggest this, because Option places additional constraints" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` @@ -46,7 +46,7 @@ LL | fn used_in_trait() -> T | | | | | expected `T` because of return type | | help: consider using an impl return type: `impl Send` - | this type parameter + | expected this type parameter ... LL | "don't suggest this, because the generic param is used in the bound." | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` diff --git a/tests/ui/return/return-impl-trait.stderr b/tests/ui/return/return-impl-trait.stderr index 43d40972fcac..707f014a16f9 100644 --- a/tests/ui/return/return-impl-trait.stderr +++ b/tests/ui/return/return-impl-trait.stderr @@ -5,7 +5,7 @@ LL | fn bar() -> T | - - | | | | | expected `T` because of return type - | this type parameter help: consider using an impl return type: `impl Trait + std::marker::Sync + Send` + | expected this type parameter help: consider using an impl return type: `impl Trait + std::marker::Sync + Send` ... LL | () | ^^ expected type parameter `T`, found `()` @@ -21,7 +21,7 @@ LL | fn other_bounds() -> T | | | | | expected `T` because of return type | | help: consider using an impl return type: `impl Trait` - | this type parameter + | expected this type parameter ... LL | () | ^^ expected type parameter `T`, found `()` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index ad11c090f122..6d436018bf4b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,14 +1,12 @@ -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/assoc-type-const-bound-usage.rs:12:6 +error[E0308]: mismatched types + --> $DIR/assoc-type-const-bound-usage.rs:12:5 | LL | ::Assoc::foo(); - | ^ the trait `Foo` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` | -help: consider further restricting this bound - | -LL | const fn foo() { - | +++++ + = note: expected constant `host` + found constant `true` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs new file mode 100644 index 000000000000..c38b4b3f1a2e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -0,0 +1,504 @@ +#![crate_type = "lib"] +#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)] +#![feature(fundamental)] +#![feature(const_trait_impl, effects, const_mut_refs)] +#![allow(internal_features)] +#![no_std] +#![no_core] + +// known-bug: #110395 + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[lang = "add"] +#[const_trait] +trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; +} + +// FIXME we shouldn't need to have to specify `Rhs`. +impl const Add for i32 { + type Output = i32; + fn add(self, rhs: i32) -> i32 { + loop {} + } +} + +fn foo() { + let x = 42_i32 + 43_i32; +} + +const fn bar() { + let x = 42_i32 + 43_i32; +} + + +#[lang = "Try"] +#[const_trait] +trait Try: FromResidual { + type Output; + type Residual; + + #[lang = "from_output"] + fn from_output(output: Self::Output) -> Self; + + #[lang = "branch"] + fn branch(self) -> ControlFlow; +} + +// FIXME +// #[const_trait] +trait FromResidual::Residual> { + #[lang = "from_residual"] + fn from_residual(residual: R) -> Self; +} + +enum ControlFlow { + #[lang = "Continue"] + Continue(C), + #[lang = "Break"] + Break(B), +} + +#[const_trait] +#[lang = "fn"] +#[rustc_paren_sugar] +trait Fn: ~const FnMut { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_mut"] +#[rustc_paren_sugar] +trait FnMut: ~const FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_once"] +#[rustc_paren_sugar] +trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct ConstFnMutClosure { + data: CapturedData, + func: Function, +} + +#[lang = "tuple_trait"] +pub trait Tuple {} + +macro_rules! impl_fn_mut_tuple { + ($($var:ident)*) => { + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue, + Function: ~const Destruct, + { + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + Function: ~const Destruct, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } + }; +} +//impl_fn_mut_tuple!(A); +//impl_fn_mut_tuple!(A B); +//impl_fn_mut_tuple!(A B C); +//impl_fn_mut_tuple!(A B C D); +//impl_fn_mut_tuple!(A B C D E); + +#[lang = "receiver"] +trait Receiver {} + +impl Receiver for &T {} + +impl Receiver for &mut T {} + +#[lang = "destruct"] +#[const_trait] +trait Destruct {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +#[lang = "drop"] +#[const_trait] +trait Drop { + fn drop(&mut self); +} + +/* +#[const_trait] +trait Residual { + type TryType: ~const Try + Try; +} +*/ + +const fn size_of() -> usize { + 42 +} + +impl Copy for u8 {} + +impl usize { + #[rustc_allow_incoherent_impl] + const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; size_of::()]) + } + #[rustc_allow_incoherent_impl] + const fn from_ne_bytes(bytes: [u8; size_of::()]) -> Self { + loop {} + } +} + +#[rustc_do_not_const_check] // hooked by const-eval +const fn panic_display() { + panic_fmt(); +} + +fn panic_fmt() {} + +#[lang = "index"] +#[const_trait] +trait Index { + type Output: ?Sized; + + fn index(&self, index: Idx) -> &Self::Output; +} + + +#[const_trait] +unsafe trait SliceIndex { + type Output: ?Sized; + fn index(self, slice: &T) -> &Self::Output; +} + +impl const Index for [T] +where + I: ~const SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} +/* FIXME +impl const Index for [T; N] +where + [T]: ~const Index, +{ + type Output = <[T] as Index>::Output; + + #[inline] + // FIXME: make `Self::Output` act like `>::Output` + fn index(&self, index: I) -> &<[T] as Index>::Output { + Index::index(self as &[T], index) + } +} +*/ + +#[lang = "unsize"] +trait Unsize { +} + +#[lang = "coerce_unsized"] +trait CoerceUnsized { +} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} + + +#[lang = "deref"] +// #[const_trait] FIXME +trait Deref { + #[lang = "deref_target"] + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; +} + + +impl /* const */ Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +impl /* const */ Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +enum Option { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), +} + +impl Option { + const fn as_ref(&self) -> Option<&T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } + + const fn as_mut(&mut self) -> Option<&mut T> { + match *self { + Some(ref mut x) => Some(x), + None => None, + } + } +} + +use Option::*; + +/* +const fn as_deref(opt: &Option) -> Option<&T::Target> +where + T: ~const Deref, +{ + match opt { + Option::Some(t) => Option::Some(t.deref()), + Option::None => Option::None, + } +} +*/ + +#[const_trait] +trait Into: Sized { + fn into(self) -> T; +} + +#[const_trait] +trait From: Sized { + fn from(value: T) -> Self; +} + +impl const Into for T +where + U: ~const From, +{ + fn into(self) -> U { + U::from(self) + } +} + +impl const From for T { + fn from(t: T) -> T { + t + } +} + +enum Result { + Ok(T), + Err(E), +} +use Result::*; + +fn from_str(s: &str) -> Result { + match s { + "true" => Ok(true), + "false" => Ok(false), + _ => Err(()), + } +} + +#[lang = "eq"] +#[const_trait] +trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +// FIXME(effects): again, this should not error without Rhs specified +impl PartialEq for str { + fn eq(&self, other: &str) -> bool { + loop {} + } +} + + +#[lang = "not"] +#[const_trait] +trait Not { + type Output; + fn not(self) -> Self::Output; +} + +impl const Not for bool { + type Output = bool; + fn not(self) -> bool { + !self + } +} + +impl Copy for bool {} +impl<'a> Copy for &'a str {} + +#[lang = "pin"] +#[fundamental] +#[repr(transparent)] +struct Pin

{ + pointer: P, +} + +impl

Pin

{ + #[lang = "new_unchecked"] + const unsafe fn new_unchecked(pointer: P) -> Pin

{ + Pin { pointer } + } +} + +impl<'a, T: ?Sized> Pin<&'a T> { + const fn get_ref(self) -> &'a T { + self.pointer + } +} + + +impl Pin

{ + /* const */ fn as_ref(&self) -> Pin<&P::Target> + where + P: /* ~const */ Deref, + { + unsafe { Pin::new_unchecked(&*self.pointer) } + } +} + + +impl<'a, T: ?Sized> Pin<&'a mut T> { + const unsafe fn get_unchecked_mut(self) -> &'a mut T { + self.pointer + } +} +/* FIXME lol +impl Option { + const fn as_pin_ref(self: Pin<&Self>) -> Option> { + match Pin::get_ref(self).as_ref() { + Some(x) => unsafe { Some(Pin::new_unchecked(x)) }, + None => None, + } + } + + const fn as_pin_mut(self: Pin<&mut Self>) -> Option> { + unsafe { + match Pin::get_unchecked_mut(self).as_mut() { + Some(x) => Some(Pin::new_unchecked(x)), + None => None, + } + } + } +} +*/ + +impl /* const */ Deref for Pin

{ + type Target = P::Target; + fn deref(&self) -> &P::Target { + Pin::get_ref(Pin::as_ref(self)) + } +} + +impl /* const */ Deref for Option { + type Target = T; + fn deref(&self) -> &T { + loop {} + } +} + +impl Receiver for Pin

{} + +impl Clone for RefCell { + fn clone(&self) -> RefCell { + RefCell::new(self.borrow().clone()) + } +} + +struct RefCell { + borrow: UnsafeCell<()>, + value: UnsafeCell, +} +impl RefCell { + const fn new(value: T) -> RefCell { + loop {} + } +} +impl RefCell { + fn borrow(&self) -> Ref<'_, T> { + loop {} + } +} + +#[lang = "unsafe_cell"] +#[repr(transparent)] +struct UnsafeCell { + value: T, +} + +struct Ref<'b, T: ?Sized + 'b> { + value: *const T, + borrow: &'b UnsafeCell<()>, +} + +impl Deref for Ref<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + loop {} + } +} + +#[lang = "clone"] +#[rustc_trivial_field_reads] +#[const_trait] +trait Clone: Sized { + fn clone(&self) -> Self; + fn clone_from(&mut self, source: &Self) + where + Self: ~const Destruct, + { + *self = source.clone() + } +} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +#[lang = "structural_teq"] +trait StructuralEq {} + +const fn drop(_: T) {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr new file mode 100644 index 000000000000..024293742189 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr @@ -0,0 +1,32 @@ +error[E0369]: cannot add `i32` to `i32` + --> $DIR/minicore.rs:33:20 + | +LL | let x = 42_i32 + 43_i32; + | ------ ^ ------ i32 + | | + | i32 + +error[E0369]: cannot add `i32` to `i32` + --> $DIR/minicore.rs:37:20 + | +LL | let x = 42_i32 + 43_i32; + | ------ ^ ------ i32 + | | + | i32 + +error[E0600]: cannot apply unary operator `!` to type `bool` + --> $DIR/minicore.rs:343:9 + | +LL | !self.eq(other) + | ^^^^^^^^^^^^^^^ cannot apply unary operator `!` + +error[E0600]: cannot apply unary operator `!` to type `bool` + --> $DIR/minicore.rs:365:9 + | +LL | !self + | ^^^^^ cannot apply unary operator `!` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0369, E0600. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs new file mode 100644 index 000000000000..b30d7743edfc --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(const_trait_impl, effects)] + +pub trait Owo::T> {} + +#[const_trait] +pub trait Uwu: Owo { + type T; +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index c94563d3591b..2a9647da7823 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,35 +1,21 @@ -error[E0277]: the trait bound `T: ~const Bar` is not satisfied +error[E0308]: mismatched types --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^ the trait `Bar` is not implemented for `T` + | ^^^^^^ expected `host`, found `true` | -note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause-const.rs:15:24 - | -LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound - | -LL | const fn test1() { - | +++++ + = note: expected constant `host` + found constant `true` -error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:12 +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:23:5 | LL | T::c::(); - | ^ the trait `Bar` is not implemented for `T` + | ^^^^^^^^^^^ expected `host`, found `true` | -note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause-const.rs:16:13 - | -LL | fn c(); - | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound - | -LL | const fn test1() { - | +++++ + = note: expected constant `host` + found constant `true` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr index 36372b644d6e..18ffd15427f8 100644 --- a/tests/ui/self/self-impl.stderr +++ b/tests/ui/self/self-impl.stderr @@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:23:16 | LL | let _: ::Baz = true; - | ^^^^^^^^^^^ help: use the fully-qualified path: `::Baz` + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Baz` error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:25:16 | LL | let _: Self::Baz = true; - | ^^^^^^^^^ help: use the fully-qualified path: `::Baz` + | ^^^^^^^^^ help: use fully-qualified syntax: `::Baz` error: aborting due to 2 previous errors diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr index acfddaf37607..0c9d2aad5d82 100644 --- a/tests/ui/structs/struct-path-associated-type.stderr +++ b/tests/ui/structs/struct-path-associated-type.stderr @@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 | LL | let s = S::A {}; - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 | LL | let z = S::A:: {}; - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:35:9 | LL | S::A {} => {} - | ^^^^ help: use the fully-qualified path: `::A` + | ^^^^ help: use fully-qualified syntax: `::A` error: aborting due to 8 previous errors diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr index 0716005c679a..8c973995c34b 100644 --- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn wat(t: &T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | t.clone() | ^^^^^^^^^ expected type parameter `T`, found `&T` | diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 5093448d2ca4..7c81825e5764 100644 --- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:11:5 | LL | fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> { - | - this type parameter ----------------------- expected `Pin + Send + 'static)>>` because of return type + | - found this type parameter ----------------------- expected `Pin + Send + 'static)>>` because of return type LL | // We could instead use an `async` block, but this way we have no std spans. LL | x | ^ expected `Pin>`, found type parameter `F` @@ -30,7 +30,7 @@ error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 | LL | fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { - | - this type parameter + | - found this type parameter LL | Pin::new(x) | -------- ^ expected `Box + Send>`, found type parameter `F` | | diff --git a/tests/ui/suggestions/restrict-existing-type-bounds.stderr b/tests/ui/suggestions/restrict-existing-type-bounds.stderr index 14a244b790a6..fe8338c18c2b 100644 --- a/tests/ui/suggestions/restrict-existing-type-bounds.stderr +++ b/tests/ui/suggestions/restrict-existing-type-bounds.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/restrict-existing-type-bounds.rs:13:12 | LL | impl TryAdd for Option { - | - this type parameter + | - found this type parameter ... LL | Ok(self) | -- ^^^^ expected `Option<::Output>`, found `Option` @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/restrict-existing-type-bounds.rs:26:12 | LL | impl> TryAdd for Other { - | - this type parameter + | - found this type parameter ... LL | Ok(self) | -- ^^^^ expected `Other<::Output>`, found `Other` diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr index 0ca5b9b92079..0d1eed67c55e 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38 | LL | impl Foo for Bar where for<'a> <&'a S>::Item: Foo {} - | ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item` + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item` error: aborting due to previous error diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 7deb9a4342d9..980c2455c8e4 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -124,7 +124,7 @@ error[E0308]: mismatched types --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9 | LL | fn baz>(x: T) { - | - this type parameter + | - found this type parameter LL | qux(x.func()) | --- ^^^^^^^^ expected `usize`, found type parameter `D` | | diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index db807a38830a..c57921a08aab 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-52893.rs:53:22 | LL | impl AddClass for Class

- | - this type parameter + | - expected this type parameter ... LL | builder.push(output); | ---- ^^^^^^ expected type parameter `F`, found `Class

` diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index f53813189254..af2e07632121 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -159,13 +159,13 @@ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:116:12 | LL | let _: S::B; - | ^^^^ help: use the fully-qualified path: `::B` + | ^^^^ help: use fully-qualified syntax: `::B` error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:117:12 | LL | let _: S::C; - | ^^^^ help: use the fully-qualified path: `::C` + | ^^^^ help: use fully-qualified syntax: `::C` error[E0624]: associated type `A` is private --> $DIR/item-privacy.rs:119:12 diff --git a/tests/ui/traits/new-solver/object-unsafety.stderr b/tests/ui/traits/new-solver/object-unsafety.stderr index bb7c68b8941f..914a8f9d4c5f 100644 --- a/tests/ui/traits/new-solver/object-unsafety.stderr +++ b/tests/ui/traits/new-solver/object-unsafety.stderr @@ -42,7 +42,7 @@ error[E0308]: mismatched types LL | pub fn copy_any(t: &T) -> T { | - - expected `T` because of return type | | - | this type parameter + | expected this type parameter LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index e24cb11288e2..96a5c1327633 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:13:25 | LL | impl Enum { - | - this type parameter + | - expected this type parameter LL | fn ts_variant() { LL | Self::TSVariant(()); | --------------- ^^ expected type parameter `T`, found `()` @@ -50,7 +50,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:17:31 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::TSVariant(()); | --------------------- ^^ expected type parameter `T`, found `()` @@ -98,7 +98,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:26:29 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::SVariant { v: () }; | ^^ expected type parameter `T`, found `()` @@ -125,7 +125,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:28:35 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::SVariant::<()> { v: () }; | ^^ expected type parameter `T`, found `()` @@ -158,7 +158,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:31:35 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::SVariant { v: () }; | ^^ expected type parameter `T`, found `()` @@ -206,7 +206,7 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:34:41 | LL | impl Enum { - | - this type parameter + | - expected this type parameter ... LL | Self::<()>::SVariant::<()> { v: () }; | ^^ expected type parameter `T`, found `()` diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index 4b09a9e743b4..844103d77a8c 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,11 +1,17 @@ error: internal compiler error: no errors encountered even though `delay_span_bug` issued -error: internal compiler error: ambiguity performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } +error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} + | + = + + +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 | LL | query(get_rpit); | ^^^^^^^^^^^^^^^ | + --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 | LL | query(get_rpit); @@ -14,7 +20,10 @@ LL | query(get_rpit); + + + query stack during panic: end of query stack -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs index 8dccd2ed46f8..0f0002f7797e 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -12,7 +12,7 @@ //[current] known-bug: #108498 //[current] failure-status: 101 //[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//[current] normalize-stderr-test: "(?m)^note: .*\n" -> "" +//[current] normalize-stderr-test: "(?m)note: .*$" -> "" //[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" //[current] normalize-stderr-test: "(?m)^ *at .*\n" -> "" diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs new file mode 100644 index 000000000000..9d7e647dd943 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs @@ -0,0 +1,18 @@ +// The canonical query `Projection(::Output = Opaque)` +// is the *only* site that defines `Opaque` in MIR typeck. +// +// check-pass + +#![feature(type_alias_impl_trait)] + +type Opaque = impl Sized; + +fn get_rpit() -> impl Sized {} + +fn query(_: impl FnOnce() -> Opaque) {} + +fn test(_: Opaque) { + query(get_rpit); +} + +fn main() {} diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index f9cdb280e276..0b705d467ffb 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -40,7 +40,7 @@ error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:9 | LL | fn index<'a, K, V>(map: &'a HashMap, k: K) -> &'a V { - | - this type parameter + | - found this type parameter LL | map[k] | ^ expected `&K`, found type parameter `K` | @@ -55,7 +55,7 @@ error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | fn index<'a, K, V>(map: &'a HashMap, k: K) -> &'a V { - | - this type parameter ----- expected `&'a V` because of return type + | - found this type parameter ----- expected `&'a V` because of return type LL | map[k] | ^^^^^^ expected `&V`, found type parameter `V` | diff --git a/tests/ui/typeck/issue-107087.stderr b/tests/ui/typeck/issue-107087.stderr index 70f19320802b..8921e3f7694d 100644 --- a/tests/ui/typeck/issue-107087.stderr +++ b/tests/ui/typeck/issue-107087.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-107087.rs:16:5 | LL | A::B::<>::C - | ^^^^^^^^ help: use the fully-qualified path: ` as Foo>::B` + | ^^^^^^^^ help: use fully-qualified syntax: ` as Foo>::B` error: aborting due to previous error diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr index 0c15c03a7408..75374fa6121e 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type --> $DIR/issue-110052.rs:6:30 | LL | for<'iter> dyn Validator<<&'iter I>::Item>:, - | ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item` + | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item` error: aborting due to previous error diff --git a/tests/ui/typeck/issue-13853.stderr b/tests/ui/typeck/issue-13853.stderr index 8ecb8b680160..0683c782933a 100644 --- a/tests/ui/typeck/issue-13853.stderr +++ b/tests/ui/typeck/issue-13853.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-13853.rs:14:9 | LL | fn nodes<'a, I: Iterator>(&self) -> I - | - this type parameter - expected `I` because of return type + | - expected this type parameter - expected `I` because of return type ... LL | self.iter() | ^^^^^^^^^^^ expected type parameter `I`, found `Iter<'_, N>`