mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 05:51:58 +00:00
Auto merge of #132094 - Zalathar:rollup-5r1ppqt, r=Zalathar
Rollup of 10 pull requests Successful merges: - #130225 (Rename Receiver -> LegacyReceiver) - #131169 (Fix `target_vendor` in QNX Neutrino targets) - #131623 (misc cleanups) - #131756 (Deeply normalize `TypeTrace` when reporting type error in new solver) - #131898 (minor `*dyn` cast cleanup) - #131909 (Prevent overflowing enum cast from ICEing) - #131930 (Don't allow test revisions that conflict with built in cfgs) - #131956 (coverage: Pass coverage mappings to LLVM as separate structs) - #132076 (HashStable for rustc_feature::Features: stop hashing compile-time constant) - #132088 (Print safety correctly in extern static items) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
55b7f8e800
@ -38,7 +38,6 @@ impl<'a> State<'a> {
|
||||
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
|
||||
}
|
||||
ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
|
||||
self.print_safety(*safety);
|
||||
self.print_item_const(
|
||||
ident,
|
||||
Some(*mutability),
|
||||
@ -46,6 +45,7 @@ impl<'a> State<'a> {
|
||||
ty,
|
||||
expr.as_deref(),
|
||||
vis,
|
||||
*safety,
|
||||
ast::Defaultness::Final,
|
||||
)
|
||||
}
|
||||
@ -84,10 +84,12 @@ impl<'a> State<'a> {
|
||||
ty: &ast::Ty,
|
||||
body: Option<&ast::Expr>,
|
||||
vis: &ast::Visibility,
|
||||
safety: ast::Safety,
|
||||
defaultness: ast::Defaultness,
|
||||
) {
|
||||
self.head("");
|
||||
self.print_visibility(vis);
|
||||
self.print_safety(safety);
|
||||
self.print_defaultness(defaultness);
|
||||
let leading = match mutbl {
|
||||
None => "const",
|
||||
@ -181,6 +183,7 @@ impl<'a> State<'a> {
|
||||
ty,
|
||||
body.as_deref(),
|
||||
&item.vis,
|
||||
ast::Safety::Default,
|
||||
ast::Defaultness::Final,
|
||||
);
|
||||
}
|
||||
@ -192,6 +195,7 @@ impl<'a> State<'a> {
|
||||
ty,
|
||||
expr.as_deref(),
|
||||
&item.vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
);
|
||||
}
|
||||
@ -549,6 +553,7 @@ impl<'a> State<'a> {
|
||||
ty,
|
||||
expr.as_deref(),
|
||||
vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
);
|
||||
}
|
||||
|
@ -619,11 +619,11 @@ pub fn eval_condition(
|
||||
// we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
|
||||
// and `true`, and we want to keep the former working without feature gate
|
||||
gate_cfg(
|
||||
&((
|
||||
&(
|
||||
if *b { kw::True } else { kw::False },
|
||||
sym::cfg_boolean_literals,
|
||||
|features: &Features| features.cfg_boolean_literals(),
|
||||
)),
|
||||
),
|
||||
cfg.span(),
|
||||
sess,
|
||||
features,
|
||||
|
@ -65,6 +65,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
||||
UniverseInfoInner::RelateTys { expected, found } => {
|
||||
let err = mbcx.infcx.err_ctxt().report_mismatched_types(
|
||||
&cause,
|
||||
mbcx.param_env,
|
||||
expected,
|
||||
found,
|
||||
TypeError::RegionsPlaceholderMismatch,
|
||||
@ -480,12 +481,11 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
|
||||
.try_report_from_nll()
|
||||
.or_else(|| {
|
||||
if let SubregionOrigin::Subtype(trace) = cause {
|
||||
Some(
|
||||
infcx.err_ctxt().report_and_explain_type_error(
|
||||
Some(infcx.err_ctxt().report_and_explain_type_error(
|
||||
*trace,
|
||||
infcx.tcx.param_env(generic_param_scope),
|
||||
TypeError::RegionsPlaceholderMismatch,
|
||||
),
|
||||
)
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -959,13 +959,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
None
|
||||
}
|
||||
}
|
||||
hir::ExprKind::MethodCall(_, _, args, span) => {
|
||||
if let Some(def_id) = typeck_results.type_dependent_def_id(*hir_id) {
|
||||
Some((def_id, *span, *args))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
hir::ExprKind::MethodCall(_, _, args, span) => typeck_results
|
||||
.type_dependent_def_id(*hir_id)
|
||||
.map(|def_id| (def_id, *span, *args)),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
@ -360,6 +360,7 @@ fn check_opaque_type_well_formed<'tcx>(
|
||||
.err_ctxt()
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(definition_span, def_id),
|
||||
param_env,
|
||||
opaque_ty,
|
||||
definition_ty,
|
||||
err,
|
||||
|
@ -47,12 +47,12 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
impl<T: ?Sized> Receiver for Box<T> {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: ?Sized> LegacyReceiver for Box<T> {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub unsafe trait Copy {}
|
||||
|
@ -44,12 +44,12 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
impl<T: ?Sized, A: Allocator> Receiver for Box<T, A> {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub unsafe trait Copy {}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use rustc_middle::mir::coverage::{
|
||||
ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion,
|
||||
};
|
||||
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion};
|
||||
|
||||
/// Must match the layout of `LLVMRustCounterKind`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub enum CounterKind {
|
||||
pub(crate) enum CounterKind {
|
||||
Zero = 0,
|
||||
CounterValueReference = 1,
|
||||
Expression = 2,
|
||||
@ -25,9 +23,9 @@ pub enum CounterKind {
|
||||
/// Must match the layout of `LLVMRustCounter`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Counter {
|
||||
pub(crate) struct Counter {
|
||||
// Important: The layout (order and types of fields) must match its C++ counterpart.
|
||||
pub kind: CounterKind,
|
||||
pub(crate) kind: CounterKind,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
@ -36,7 +34,7 @@ impl Counter {
|
||||
pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 };
|
||||
|
||||
/// Constructs a new `Counter` of kind `CounterValueReference`.
|
||||
pub fn counter_value_reference(counter_id: CounterId) -> Self {
|
||||
pub(crate) fn counter_value_reference(counter_id: CounterId) -> Self {
|
||||
Self { kind: CounterKind::CounterValueReference, id: counter_id.as_u32() }
|
||||
}
|
||||
|
||||
@ -59,7 +57,7 @@ impl Counter {
|
||||
/// Must match the layout of `LLVMRustCounterExprKind`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub enum ExprKind {
|
||||
pub(crate) enum ExprKind {
|
||||
Subtract = 0,
|
||||
Add = 1,
|
||||
}
|
||||
@ -69,48 +67,13 @@ pub enum ExprKind {
|
||||
/// Must match the layout of `LLVMRustCounterExpression`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct CounterExpression {
|
||||
pub kind: ExprKind,
|
||||
pub lhs: Counter,
|
||||
pub rhs: Counter,
|
||||
pub(crate) struct CounterExpression {
|
||||
pub(crate) kind: ExprKind,
|
||||
pub(crate) lhs: Counter,
|
||||
pub(crate) rhs: Counter,
|
||||
}
|
||||
|
||||
/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`.
|
||||
///
|
||||
/// Must match the layout of `LLVMRustCounterMappingRegionKind`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
enum RegionKind {
|
||||
/// A CodeRegion associates some code with a counter
|
||||
CodeRegion = 0,
|
||||
|
||||
/// An ExpansionRegion represents a file expansion region that associates
|
||||
/// a source range with the expansion of a virtual source file, such as
|
||||
/// for a macro instantiation or #include file.
|
||||
ExpansionRegion = 1,
|
||||
|
||||
/// A SkippedRegion represents a source range with code that was skipped
|
||||
/// by a preprocessor or similar means.
|
||||
SkippedRegion = 2,
|
||||
|
||||
/// A GapRegion is like a CodeRegion, but its count is only set as the
|
||||
/// line execution count when its the only region in the line.
|
||||
GapRegion = 3,
|
||||
|
||||
/// A BranchRegion represents leaf-level boolean expressions and is
|
||||
/// associated with two counters, each representing the number of times the
|
||||
/// expression evaluates to true or false.
|
||||
BranchRegion = 4,
|
||||
|
||||
/// A DecisionRegion represents a top-level boolean expression and is
|
||||
/// associated with a variable length bitmap index and condition number.
|
||||
MCDCDecisionRegion = 5,
|
||||
|
||||
/// A Branch Region can be extended to include IDs to facilitate MC/DC.
|
||||
MCDCBranchRegion = 6,
|
||||
}
|
||||
|
||||
mod mcdc {
|
||||
pub(crate) mod mcdc {
|
||||
use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo};
|
||||
|
||||
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
||||
@ -121,8 +84,6 @@ mod mcdc {
|
||||
num_conditions: u16,
|
||||
}
|
||||
|
||||
// ConditionId in llvm is `unsigned int` at 18 while `int16_t` at
|
||||
// [19](https://github.com/llvm/llvm-project/pull/81257).
|
||||
type LLVMConditionId = i16;
|
||||
|
||||
/// Must match the layout of `LLVMRustMCDCBranchParameters`.
|
||||
@ -133,38 +94,6 @@ mod mcdc {
|
||||
condition_ids: [LLVMConditionId; 2],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum ParameterTag {
|
||||
None = 0,
|
||||
Decision = 1,
|
||||
Branch = 2,
|
||||
}
|
||||
/// Same layout with `LLVMRustMCDCParameters`
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) struct Parameters {
|
||||
tag: ParameterTag,
|
||||
decision_params: DecisionParameters,
|
||||
branch_params: BranchParameters,
|
||||
}
|
||||
|
||||
impl Parameters {
|
||||
pub(crate) fn none() -> Self {
|
||||
Self {
|
||||
tag: ParameterTag::None,
|
||||
decision_params: Default::default(),
|
||||
branch_params: Default::default(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn decision(decision_params: DecisionParameters) -> Self {
|
||||
Self { tag: ParameterTag::Decision, decision_params, branch_params: Default::default() }
|
||||
}
|
||||
pub(crate) fn branch(branch_params: BranchParameters) -> Self {
|
||||
Self { tag: ParameterTag::Branch, decision_params: Default::default(), branch_params }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConditionInfo> for BranchParameters {
|
||||
fn from(value: ConditionInfo) -> Self {
|
||||
let to_llvm_cond_id = |cond_id: Option<ConditionId>| {
|
||||
@ -186,267 +115,68 @@ mod mcdc {
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
|
||||
/// coverage map, in accordance with the
|
||||
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
|
||||
/// The struct composes fields representing the `Counter` type and value(s) (injected counter
|
||||
/// ID, or expression type and operands), the source file (an indirect index into a "filenames
|
||||
/// array", encoded separately), and source location (start and end positions of the represented
|
||||
/// code region).
|
||||
/// A span of source code coordinates to be embedded in coverage metadata.
|
||||
///
|
||||
/// Corresponds to struct `llvm::coverage::CounterMappingRegion`.
|
||||
///
|
||||
/// Must match the layout of `LLVMRustCounterMappingRegion`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// Must match the layout of `LLVMRustCoverageSpan`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct CounterMappingRegion {
|
||||
/// The counter type and type-dependent counter data, if any.
|
||||
counter: Counter,
|
||||
|
||||
/// If the `RegionKind` is a `BranchRegion`, this represents the counter
|
||||
/// for the false branch of the region.
|
||||
false_counter: Counter,
|
||||
|
||||
mcdc_params: mcdc::Parameters,
|
||||
/// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
|
||||
/// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
|
||||
/// that, in turn, are used to look up the filename for this region.
|
||||
pub(crate) struct CoverageSpan {
|
||||
/// Local index into the function's local-to-global file ID table.
|
||||
/// The value at that index is itself an index into the coverage filename
|
||||
/// table in the CGU's `__llvm_covmap` section.
|
||||
file_id: u32,
|
||||
|
||||
/// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find
|
||||
/// the mapping regions created as a result of macro expansion, by checking if their file id
|
||||
/// matches the expanded file id.
|
||||
expanded_file_id: u32,
|
||||
|
||||
/// 1-based starting line of the mapping region.
|
||||
/// 1-based starting line of the source code span.
|
||||
start_line: u32,
|
||||
|
||||
/// 1-based starting column of the mapping region.
|
||||
/// 1-based starting column of the source code span.
|
||||
start_col: u32,
|
||||
|
||||
/// 1-based ending line of the mapping region.
|
||||
/// 1-based ending line of the source code span.
|
||||
end_line: u32,
|
||||
|
||||
/// 1-based ending column of the mapping region. If the high bit is set, the current
|
||||
/// mapping region is a gap area.
|
||||
/// 1-based ending column of the source code span. High bit must be unset.
|
||||
end_col: u32,
|
||||
|
||||
kind: RegionKind,
|
||||
}
|
||||
|
||||
impl CounterMappingRegion {
|
||||
pub(crate) fn from_mapping(
|
||||
mapping_kind: &MappingKind,
|
||||
local_file_id: u32,
|
||||
source_region: &SourceRegion,
|
||||
) -> Self {
|
||||
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } =
|
||||
source_region;
|
||||
match *mapping_kind {
|
||||
MappingKind::Code(term) => Self::code_region(
|
||||
Counter::from_term(term),
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
MappingKind::Branch { true_term, false_term } => Self::branch_region(
|
||||
Counter::from_term(true_term),
|
||||
Counter::from_term(false_term),
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
|
||||
Self::mcdc_branch_region(
|
||||
Counter::from_term(true_term),
|
||||
Counter::from_term(false_term),
|
||||
mcdc_params,
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
)
|
||||
}
|
||||
MappingKind::MCDCDecision(decision_info) => Self::decision_region(
|
||||
decision_info,
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
impl CoverageSpan {
|
||||
pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self {
|
||||
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
|
||||
// Internally, LLVM uses the high bit of `end_col` to distinguish between
|
||||
// code regions and gap regions, so it can't be used by the column number.
|
||||
assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}");
|
||||
Self { file_id, start_line, start_col, end_line, end_col }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn code_region(
|
||||
counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::CodeRegion,
|
||||
}
|
||||
/// Must match the layout of `LLVMRustCoverageCodeRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct CodeRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) counter: Counter,
|
||||
}
|
||||
|
||||
pub(crate) fn branch_region(
|
||||
counter: Counter,
|
||||
false_counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::BranchRegion,
|
||||
}
|
||||
/// Must match the layout of `LLVMRustCoverageBranchRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct BranchRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) true_counter: Counter,
|
||||
pub(crate) false_counter: Counter,
|
||||
}
|
||||
|
||||
pub(crate) fn mcdc_branch_region(
|
||||
counter: Counter,
|
||||
false_counter: Counter,
|
||||
condition_info: ConditionInfo,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter,
|
||||
mcdc_params: mcdc::Parameters::branch(condition_info.into()),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::MCDCBranchRegion,
|
||||
}
|
||||
/// Must match the layout of `LLVMRustCoverageMCDCBranchRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct MCDCBranchRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) true_counter: Counter,
|
||||
pub(crate) false_counter: Counter,
|
||||
pub(crate) mcdc_branch_params: mcdc::BranchParameters,
|
||||
}
|
||||
|
||||
pub(crate) fn decision_region(
|
||||
decision_info: DecisionInfo,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
let mcdc_params = mcdc::Parameters::decision(decision_info.into());
|
||||
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params,
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::MCDCDecisionRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn expansion_region(
|
||||
file_id: u32,
|
||||
expanded_file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::ExpansionRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn skipped_region(
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::SkippedRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn gap_region(
|
||||
counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col: (1_u32 << 31) | end_col,
|
||||
kind: RegionKind::GapRegion,
|
||||
}
|
||||
}
|
||||
/// Must match the layout of `LLVMRustCoverageMCDCDecisionRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct MCDCDecisionRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) mcdc_decision_params: mcdc::DecisionParameters,
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::coverage::MappingKind;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_span::Symbol;
|
||||
@ -12,7 +13,7 @@ use rustc_span::def_id::DefIdSet;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo::ffi::CounterMappingRegion;
|
||||
use crate::coverageinfo::ffi;
|
||||
use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
|
||||
use crate::{coverageinfo, llvm};
|
||||
|
||||
@ -237,7 +238,10 @@ fn encode_mappings_for_function(
|
||||
let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
|
||||
|
||||
let mut virtual_file_mapping = VirtualFileMapping::default();
|
||||
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
|
||||
let mut code_regions = vec![];
|
||||
let mut branch_regions = vec![];
|
||||
let mut mcdc_branch_regions = vec![];
|
||||
let mut mcdc_decision_regions = vec![];
|
||||
|
||||
// Group mappings into runs with the same filename, preserving the order
|
||||
// yielded by `FunctionCoverage`.
|
||||
@ -257,11 +261,36 @@ fn encode_mappings_for_function(
|
||||
// form suitable for FFI.
|
||||
for (mapping_kind, region) in counter_regions_for_file {
|
||||
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
|
||||
mapping_regions.push(CounterMappingRegion::from_mapping(
|
||||
&mapping_kind,
|
||||
local_file_id.as_u32(),
|
||||
region,
|
||||
));
|
||||
let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region);
|
||||
match mapping_kind {
|
||||
MappingKind::Code(term) => {
|
||||
code_regions
|
||||
.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
|
||||
}
|
||||
MappingKind::Branch { true_term, false_term } => {
|
||||
branch_regions.push(ffi::BranchRegion {
|
||||
span,
|
||||
true_counter: ffi::Counter::from_term(true_term),
|
||||
false_counter: ffi::Counter::from_term(false_term),
|
||||
});
|
||||
}
|
||||
MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
|
||||
mcdc_branch_regions.push(ffi::MCDCBranchRegion {
|
||||
span,
|
||||
true_counter: ffi::Counter::from_term(true_term),
|
||||
false_counter: ffi::Counter::from_term(false_term),
|
||||
mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params),
|
||||
});
|
||||
}
|
||||
MappingKind::MCDCDecision(mcdc_decision_params) => {
|
||||
mcdc_decision_regions.push(ffi::MCDCDecisionRegion {
|
||||
span,
|
||||
mcdc_decision_params: ffi::mcdc::DecisionParameters::from(
|
||||
mcdc_decision_params,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +299,10 @@ fn encode_mappings_for_function(
|
||||
coverageinfo::write_mapping_to_buffer(
|
||||
virtual_file_mapping.into_vec(),
|
||||
expressions,
|
||||
mapping_regions,
|
||||
&code_regions,
|
||||
&branch_regions,
|
||||
&mcdc_branch_regions,
|
||||
&mcdc_decision_regions,
|
||||
buffer,
|
||||
);
|
||||
})
|
||||
|
@ -18,7 +18,6 @@ use tracing::{debug, instrument};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
|
||||
use crate::coverageinfo::map_data::FunctionCoverageCollector;
|
||||
use crate::llvm;
|
||||
|
||||
@ -257,8 +256,11 @@ pub(crate) fn write_filenames_section_to_buffer<'a>(
|
||||
|
||||
pub(crate) fn write_mapping_to_buffer(
|
||||
virtual_file_mapping: Vec<u32>,
|
||||
expressions: Vec<CounterExpression>,
|
||||
mapping_regions: Vec<CounterMappingRegion>,
|
||||
expressions: Vec<ffi::CounterExpression>,
|
||||
code_regions: &[ffi::CodeRegion],
|
||||
branch_regions: &[ffi::BranchRegion],
|
||||
mcdc_branch_regions: &[ffi::MCDCBranchRegion],
|
||||
mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
|
||||
buffer: &RustString,
|
||||
) {
|
||||
unsafe {
|
||||
@ -267,8 +269,14 @@ pub(crate) fn write_mapping_to_buffer(
|
||||
virtual_file_mapping.len() as c_uint,
|
||||
expressions.as_ptr(),
|
||||
expressions.len() as c_uint,
|
||||
mapping_regions.as_ptr(),
|
||||
mapping_regions.len() as c_uint,
|
||||
code_regions.as_ptr(),
|
||||
code_regions.len() as c_uint,
|
||||
branch_regions.as_ptr(),
|
||||
branch_regions.len() as c_uint,
|
||||
mcdc_branch_regions.as_ptr(),
|
||||
mcdc_branch_regions.len() as c_uint,
|
||||
mcdc_decision_regions.as_ptr(),
|
||||
mcdc_decision_regions.len() as c_uint,
|
||||
buffer,
|
||||
);
|
||||
}
|
||||
|
@ -1744,7 +1744,7 @@ unsafe extern "C" {
|
||||
) -> bool;
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
pub(crate) fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
Filenames: *const *const c_char,
|
||||
FilenamesLen: size_t,
|
||||
Lengths: *const size_t,
|
||||
@ -1753,33 +1753,39 @@ unsafe extern "C" {
|
||||
);
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustCoverageWriteMappingToBuffer(
|
||||
pub(crate) fn LLVMRustCoverageWriteMappingToBuffer(
|
||||
VirtualFileMappingIDs: *const c_uint,
|
||||
NumVirtualFileMappingIDs: c_uint,
|
||||
Expressions: *const crate::coverageinfo::ffi::CounterExpression,
|
||||
NumExpressions: c_uint,
|
||||
MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion,
|
||||
NumMappingRegions: c_uint,
|
||||
CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
|
||||
NumCodeRegions: c_uint,
|
||||
BranchRegions: *const crate::coverageinfo::ffi::BranchRegion,
|
||||
NumBranchRegions: c_uint,
|
||||
MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion,
|
||||
NumMCDCBranchRegions: c_uint,
|
||||
MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion,
|
||||
NumMCDCDecisionRegions: c_uint,
|
||||
BufferOut: &RustString,
|
||||
);
|
||||
|
||||
pub fn LLVMRustCoverageCreatePGOFuncNameVar(
|
||||
pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar(
|
||||
F: &Value,
|
||||
FuncName: *const c_char,
|
||||
FuncNameLen: size_t,
|
||||
) -> &Value;
|
||||
pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
|
||||
pub(crate) fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
|
||||
pub(crate) fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
|
||||
pub(crate) fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
||||
pub(crate) fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
||||
|
||||
pub fn LLVMRustCoverageMappingVersion() -> u32;
|
||||
pub(crate) fn LLVMRustCoverageMappingVersion() -> u32;
|
||||
pub fn LLVMRustDebugMetadataVersion() -> u32;
|
||||
pub fn LLVMRustVersionMajor() -> u32;
|
||||
pub fn LLVMRustVersionMinor() -> u32;
|
||||
|
@ -241,7 +241,7 @@ language_item_table! {
|
||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
|
@ -282,6 +282,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
||||
let emitted = report_trait_method_mismatch(
|
||||
infcx,
|
||||
cause,
|
||||
param_env,
|
||||
terr,
|
||||
(trait_m, trait_sig),
|
||||
(impl_m, impl_sig),
|
||||
@ -575,10 +576,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
hir.get_if_local(impl_m.def_id)
|
||||
.and_then(|node| node.fn_decl())
|
||||
.map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),
|
||||
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||
Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
|
||||
expected: trait_return_ty.into(),
|
||||
found: impl_return_ty.into(),
|
||||
})),
|
||||
}))),
|
||||
terr,
|
||||
false,
|
||||
);
|
||||
@ -602,6 +603,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
let emitted = report_trait_method_mismatch(
|
||||
infcx,
|
||||
cause,
|
||||
param_env,
|
||||
terr,
|
||||
(trait_m, trait_sig),
|
||||
(impl_m, impl_sig),
|
||||
@ -915,6 +917,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
||||
fn report_trait_method_mismatch<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
mut cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
(trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
|
||||
(impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
|
||||
@ -1000,10 +1003,10 @@ fn report_trait_method_mismatch<'tcx>(
|
||||
&mut diag,
|
||||
&cause,
|
||||
trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)),
|
||||
Some(infer::ValuePairs::PolySigs(ExpectedFound {
|
||||
Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
|
||||
expected: ty::Binder::dummy(trait_sig),
|
||||
found: ty::Binder::dummy(impl_sig),
|
||||
})),
|
||||
}))),
|
||||
terr,
|
||||
false,
|
||||
);
|
||||
@ -1797,10 +1800,10 @@ fn compare_const_predicate_entailment<'tcx>(
|
||||
&mut diag,
|
||||
&cause,
|
||||
trait_c_span.map(|span| (span, Cow::from("type in trait"), false)),
|
||||
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||
Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
|
||||
expected: trait_ty.into(),
|
||||
found: impl_ty.into(),
|
||||
})),
|
||||
}))),
|
||||
terr,
|
||||
false,
|
||||
);
|
||||
|
@ -646,10 +646,10 @@ pub fn check_function_signature<'tcx>(
|
||||
&mut diag,
|
||||
&cause,
|
||||
None,
|
||||
Some(infer::ValuePairs::PolySigs(ExpectedFound {
|
||||
Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
|
||||
expected: expected_sig,
|
||||
found: actual_sig,
|
||||
})),
|
||||
}))),
|
||||
err,
|
||||
false,
|
||||
);
|
||||
|
@ -1801,7 +1801,7 @@ fn receiver_is_valid<'tcx>(
|
||||
autoderef = autoderef.include_raw_pointers();
|
||||
}
|
||||
|
||||
let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span));
|
||||
let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
|
||||
|
||||
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
|
||||
while let Some((potential_self_ty, _)) = autoderef.next() {
|
||||
|
@ -364,6 +364,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
||||
.err_ctxt()
|
||||
.report_mismatched_types(
|
||||
&cause,
|
||||
param_env,
|
||||
mk_ptr(mt_b.ty),
|
||||
target,
|
||||
ty::error::TypeError::Mutability,
|
||||
|
@ -862,7 +862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
Err(e) => {
|
||||
// FIXME(effects): better diagnostic
|
||||
self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
|
||||
self.err_ctxt()
|
||||
.report_mismatched_consts(&cause, self.param_env, effect, param, e)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,19 +876,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
// A<dyn Src<...> + SrcAuto> -> B<dyn Dst<...> + DstAuto>. need to make sure
|
||||
// - `Src` and `Dst` traits are the same
|
||||
// - traits have the same generic arguments
|
||||
// - `SrcAuto` is a superset of `DstAuto`
|
||||
(Some(src_principal), Some(dst_principal)) => {
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
// Check that the traits are actually the same.
|
||||
// The `dyn Src = dyn Dst` check below would suffice,
|
||||
// but this may produce a better diagnostic.
|
||||
// - projections are the same
|
||||
// - `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`
|
||||
//
|
||||
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
|
||||
// and is unaffected by this check.
|
||||
if src_principal.def_id() != dst_principal.def_id() {
|
||||
return Err(CastError::DifferingKinds { src_kind, dst_kind });
|
||||
}
|
||||
(Some(src_principal), Some(_)) => {
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
// We need to reconstruct trait object types.
|
||||
// `m_src` and `m_dst` won't work for us here because they will potentially
|
||||
@ -912,8 +906,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
ty::Dyn,
|
||||
));
|
||||
|
||||
// `dyn Src = dyn Dst`, this checks for matching traits/generics
|
||||
// This is `demand_eqtype`, but inlined to give a better error.
|
||||
// `dyn Src = dyn Dst`, this checks for matching traits/generics/projections
|
||||
// This is `fcx.demand_eqtype`, but inlined to give a better error.
|
||||
let cause = fcx.misc(self.span);
|
||||
if fcx
|
||||
.at(&cause, fcx.param_env)
|
||||
@ -965,8 +959,35 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
// dyn Auto -> dyn Auto'? ok.
|
||||
(None, None) => Ok(CastKind::PtrPtrCast),
|
||||
|
||||
// dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
|
||||
// FIXME: allow this
|
||||
// dyn Trait -> dyn Auto? not ok (for now).
|
||||
//
|
||||
// Although dropping the principal is already allowed for unsizing coercions
|
||||
// (e.g. `*const (dyn Trait + Auto)` to `*const dyn Auto`), dropping it is
|
||||
// currently **NOT** allowed for (non-coercion) ptr-to-ptr casts (e.g
|
||||
// `*const Foo` to `*const Bar` where `Foo` has a `dyn Trait + Auto` tail
|
||||
// and `Bar` has a `dyn Auto` tail), because the underlying MIR operations
|
||||
// currently work very differently:
|
||||
//
|
||||
// * A MIR unsizing coercion on raw pointers to trait objects (`*const dyn Src`
|
||||
// to `*const dyn Dst`) is currently equivalent to downcasting the source to
|
||||
// the concrete sized type that it was originally unsized from first (via a
|
||||
// ptr-to-ptr cast from `*const Src` to `*const T` with `T: Sized`) and then
|
||||
// unsizing this thin pointer to the target type (unsizing `*const T` to
|
||||
// `*const Dst`). In particular, this means that the pointer's metadata
|
||||
// (vtable) will semantically change, e.g. for const eval and miri, even
|
||||
// though the vtables will always be merged for codegen.
|
||||
//
|
||||
// * A MIR ptr-to-ptr cast is currently equivalent to a transmute and does not
|
||||
// change the pointer metadata (vtable) at all.
|
||||
//
|
||||
// In addition to this potentially surprising difference between coercion and
|
||||
// non-coercion casts, casting away the principal with a MIR ptr-to-ptr cast
|
||||
// is currently considered undefined behavior:
|
||||
//
|
||||
// As a validity invariant of pointers to trait objects, we currently require
|
||||
// that the principal of the vtable in the pointer metadata exactly matches
|
||||
// the principal of the pointee type, where "no principal" is also considered
|
||||
// a kind of principal.
|
||||
(Some(_), None) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
|
||||
|
||||
// dyn Auto -> dyn Trait? not ok.
|
||||
|
@ -1723,6 +1723,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
}) => {
|
||||
err = fcx.err_ctxt().report_mismatched_types(
|
||||
cause,
|
||||
fcx.param_env,
|
||||
expected,
|
||||
found,
|
||||
coercion_error,
|
||||
@ -1752,6 +1753,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
}) => {
|
||||
err = fcx.err_ctxt().report_mismatched_types(
|
||||
cause,
|
||||
fcx.param_env,
|
||||
expected,
|
||||
found,
|
||||
coercion_error,
|
||||
@ -1787,6 +1789,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
_ => {
|
||||
err = fcx.err_ctxt().report_mismatched_types(
|
||||
cause,
|
||||
fcx.param_env,
|
||||
expected,
|
||||
found,
|
||||
coercion_error,
|
||||
@ -1897,7 +1900,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
block_or_return_id: hir::HirId,
|
||||
expression: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
|
||||
let mut err =
|
||||
fcx.err_ctxt().report_mismatched_types(cause, fcx.param_env, expected, found, ty_err);
|
||||
|
||||
let due_to_block = matches!(fcx.tcx.hir_node(block_or_return_id), hir::Node::Block(..));
|
||||
|
||||
|
@ -191,7 +191,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.at(cause, self.param_env)
|
||||
.sup(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
.map_err(|e| {
|
||||
self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
@ -218,7 +220,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.at(cause, self.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
.map_err(|e| {
|
||||
self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn demand_coerce(
|
||||
@ -271,7 +275,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let expr = expr.peel_drop_temps();
|
||||
let cause = self.misc(expr.span);
|
||||
let expr_ty = self.resolve_vars_if_possible(checked_ty);
|
||||
let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e);
|
||||
let mut err =
|
||||
self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e);
|
||||
|
||||
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
|
||||
|
||||
|
@ -827,6 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
formal_and_expected_inputs[mismatch_idx.into()],
|
||||
provided_arg_tys[mismatch_idx.into()].0,
|
||||
),
|
||||
self.param_env,
|
||||
terr,
|
||||
);
|
||||
err.span_label(
|
||||
@ -912,7 +913,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let trace =
|
||||
mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
|
||||
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
|
||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e);
|
||||
let mut err =
|
||||
self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
|
||||
suggest_confusable(&mut err);
|
||||
reported = Some(err.emit());
|
||||
return false;
|
||||
@ -940,7 +942,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
||||
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
|
||||
let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
|
||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
|
||||
let mut err =
|
||||
self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *err);
|
||||
self.emit_coerce_suggestions(
|
||||
&mut err,
|
||||
provided_args[*provided_idx],
|
||||
@ -1113,7 +1116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&mut err,
|
||||
&trace.cause,
|
||||
None,
|
||||
Some(trace.values),
|
||||
Some(self.param_env.and(trace.values)),
|
||||
e,
|
||||
true,
|
||||
);
|
||||
|
@ -538,7 +538,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
// to the feature, like the self type can't reference method args.
|
||||
if self.tcx.features().arbitrary_self_types() {
|
||||
self.err_ctxt()
|
||||
.report_mismatched_types(&cause, method_self_ty, self_ty, terr)
|
||||
.report_mismatched_types(
|
||||
&cause,
|
||||
self.param_env,
|
||||
method_self_ty,
|
||||
self_ty,
|
||||
terr,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
// This has/will have errored in wfcheck, which we cannot depend on from here, as typeck on functions
|
||||
|
@ -537,7 +537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& binding_id != self.binding_id
|
||||
{
|
||||
if self.check_and_add_sugg_binding(LetStmt {
|
||||
ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None },
|
||||
ty_hir_id_opt: ty.map(|ty| ty.hir_id),
|
||||
binding_id,
|
||||
span: pat.span,
|
||||
init_hir_id: init.hir_id,
|
||||
|
@ -187,10 +187,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
value_count: usize,
|
||||
) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
|
||||
let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
|
||||
(
|
||||
range.start..range.end,
|
||||
(range.start..range.end).map(|index| self.var_origin(index)).collect(),
|
||||
)
|
||||
(range.clone(), range.map(|index| self.var_origin(index)).collect())
|
||||
}
|
||||
|
||||
/// Returns indices of all variables that are not yet
|
||||
|
@ -33,45 +33,6 @@ static coverage::Counter fromRust(LLVMRustCounter Counter) {
|
||||
report_fatal_error("Bad LLVMRustCounterKind!");
|
||||
}
|
||||
|
||||
// FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind`
|
||||
// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234
|
||||
enum class LLVMRustCounterMappingRegionKind {
|
||||
CodeRegion = 0,
|
||||
ExpansionRegion = 1,
|
||||
SkippedRegion = 2,
|
||||
GapRegion = 3,
|
||||
BranchRegion = 4,
|
||||
MCDCDecisionRegion = 5,
|
||||
MCDCBranchRegion = 6
|
||||
};
|
||||
|
||||
static coverage::CounterMappingRegion::RegionKind
|
||||
fromRust(LLVMRustCounterMappingRegionKind Kind) {
|
||||
switch (Kind) {
|
||||
case LLVMRustCounterMappingRegionKind::CodeRegion:
|
||||
return coverage::CounterMappingRegion::CodeRegion;
|
||||
case LLVMRustCounterMappingRegionKind::ExpansionRegion:
|
||||
return coverage::CounterMappingRegion::ExpansionRegion;
|
||||
case LLVMRustCounterMappingRegionKind::SkippedRegion:
|
||||
return coverage::CounterMappingRegion::SkippedRegion;
|
||||
case LLVMRustCounterMappingRegionKind::GapRegion:
|
||||
return coverage::CounterMappingRegion::GapRegion;
|
||||
case LLVMRustCounterMappingRegionKind::BranchRegion:
|
||||
return coverage::CounterMappingRegion::BranchRegion;
|
||||
case LLVMRustCounterMappingRegionKind::MCDCDecisionRegion:
|
||||
return coverage::CounterMappingRegion::MCDCDecisionRegion;
|
||||
case LLVMRustCounterMappingRegionKind::MCDCBranchRegion:
|
||||
return coverage::CounterMappingRegion::MCDCBranchRegion;
|
||||
}
|
||||
report_fatal_error("Bad LLVMRustCounterMappingRegionKind!");
|
||||
}
|
||||
|
||||
enum LLVMRustMCDCParametersTag {
|
||||
None = 0,
|
||||
Decision = 1,
|
||||
Branch = 2,
|
||||
};
|
||||
|
||||
struct LLVMRustMCDCDecisionParameters {
|
||||
uint32_t BitmapIdx;
|
||||
uint16_t NumConditions;
|
||||
@ -82,47 +43,58 @@ struct LLVMRustMCDCBranchParameters {
|
||||
int16_t ConditionIDs[2];
|
||||
};
|
||||
|
||||
struct LLVMRustMCDCParameters {
|
||||
LLVMRustMCDCParametersTag Tag;
|
||||
LLVMRustMCDCDecisionParameters DecisionParameters;
|
||||
LLVMRustMCDCBranchParameters BranchParameters;
|
||||
};
|
||||
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
|
||||
switch (Params.Tag) {
|
||||
case LLVMRustMCDCParametersTag::None:
|
||||
return std::monostate();
|
||||
case LLVMRustMCDCParametersTag::Decision:
|
||||
return coverage::mcdc::DecisionParameters(
|
||||
Params.DecisionParameters.BitmapIdx,
|
||||
Params.DecisionParameters.NumConditions);
|
||||
case LLVMRustMCDCParametersTag::Branch:
|
||||
static coverage::mcdc::BranchParameters
|
||||
fromRust(LLVMRustMCDCBranchParameters Params) {
|
||||
return coverage::mcdc::BranchParameters(
|
||||
static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionID),
|
||||
{static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionIDs[0]),
|
||||
static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionIDs[1])});
|
||||
Params.ConditionID, {Params.ConditionIDs[0], Params.ConditionIDs[1]});
|
||||
}
|
||||
report_fatal_error("Bad LLVMRustMCDCParametersTag!");
|
||||
|
||||
static coverage::mcdc::DecisionParameters
|
||||
fromRust(LLVMRustMCDCDecisionParameters Params) {
|
||||
return coverage::mcdc::DecisionParameters(Params.BitmapIdx,
|
||||
Params.NumConditions);
|
||||
}
|
||||
#endif
|
||||
|
||||
// FFI equivalent of struct `llvm::coverage::CounterMappingRegion`
|
||||
// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304
|
||||
struct LLVMRustCounterMappingRegion {
|
||||
LLVMRustCounter Count;
|
||||
LLVMRustCounter FalseCount;
|
||||
LLVMRustMCDCParameters MCDCParameters;
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`.
|
||||
struct LLVMRustCoverageSpan {
|
||||
uint32_t FileID;
|
||||
uint32_t ExpandedFileID;
|
||||
uint32_t LineStart;
|
||||
uint32_t ColumnStart;
|
||||
uint32_t LineEnd;
|
||||
uint32_t ColumnEnd;
|
||||
LLVMRustCounterMappingRegionKind Kind;
|
||||
};
|
||||
|
||||
// Must match the layout of `rustc_codegen_llvm::coverageinfo::ffi::CodeRegion`.
|
||||
struct LLVMRustCoverageCodeRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter Count;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`.
|
||||
struct LLVMRustCoverageBranchRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter TrueCount;
|
||||
LLVMRustCounter FalseCount;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::MCDCBranchRegion`.
|
||||
struct LLVMRustCoverageMCDCBranchRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter TrueCount;
|
||||
LLVMRustCounter FalseCount;
|
||||
LLVMRustMCDCBranchParameters MCDCBranchParams;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::MCDCDecisionRegion`.
|
||||
struct LLVMRustCoverageMCDCDecisionRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustMCDCDecisionParameters MCDCDecisionParams;
|
||||
};
|
||||
|
||||
// FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind`
|
||||
@ -174,28 +146,16 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs,
|
||||
const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions,
|
||||
const LLVMRustCounterMappingRegion *RustMappingRegions,
|
||||
unsigned NumMappingRegions, RustStringRef BufferOut) {
|
||||
const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions,
|
||||
const LLVMRustCoverageBranchRegion *BranchRegions,
|
||||
unsigned NumBranchRegions,
|
||||
const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions,
|
||||
unsigned NumMCDCBranchRegions,
|
||||
const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions,
|
||||
unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) {
|
||||
// Convert from FFI representation to LLVM representation.
|
||||
SmallVector<coverage::CounterMappingRegion, 0> MappingRegions;
|
||||
MappingRegions.reserve(NumMappingRegions);
|
||||
for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>(
|
||||
RustMappingRegions, NumMappingRegions)) {
|
||||
MappingRegions.emplace_back(
|
||||
fromRust(Region.Count), fromRust(Region.FalseCount),
|
||||
#if LLVM_VERSION_LT(19, 0)
|
||||
coverage::CounterMappingRegion::MCDCParameters{},
|
||||
#endif
|
||||
Region.FileID, Region.ExpandedFileID, // File IDs, then region info.
|
||||
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
|
||||
fromRust(Region.Kind)
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
,
|
||||
fromRust(Region.MCDCParameters)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
// Expressions:
|
||||
std::vector<coverage::CounterExpression> Expressions;
|
||||
Expressions.reserve(NumExpressions);
|
||||
for (const auto &Expression :
|
||||
@ -205,6 +165,46 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
fromRust(Expression.RHS));
|
||||
}
|
||||
|
||||
std::vector<coverage::CounterMappingRegion> MappingRegions;
|
||||
MappingRegions.reserve(NumCodeRegions + NumBranchRegions +
|
||||
NumMCDCBranchRegions + NumMCDCDecisionRegions);
|
||||
|
||||
// Code regions:
|
||||
for (const auto &Region : ArrayRef(CodeRegions, NumCodeRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeRegion(
|
||||
fromRust(Region.Count), Region.Span.FileID, Region.Span.LineStart,
|
||||
Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd));
|
||||
}
|
||||
|
||||
// Branch regions:
|
||||
for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
|
||||
fromRust(Region.TrueCount), fromRust(Region.FalseCount),
|
||||
Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart,
|
||||
Region.Span.LineEnd, Region.Span.ColumnEnd));
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
// MC/DC branch regions:
|
||||
for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
|
||||
fromRust(Region.TrueCount), fromRust(Region.FalseCount),
|
||||
Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart,
|
||||
Region.Span.LineEnd, Region.Span.ColumnEnd,
|
||||
fromRust(Region.MCDCBranchParams)));
|
||||
}
|
||||
|
||||
// MC/DC decision regions:
|
||||
for (const auto &Region :
|
||||
ArrayRef(MCDCDecisionRegions, NumMCDCDecisionRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeDecisionRegion(
|
||||
fromRust(Region.MCDCDecisionParams), Region.Span.FileID,
|
||||
Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd,
|
||||
Region.Span.ColumnEnd));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write the converted expressions and mappings to a byte buffer.
|
||||
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
|
||||
ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
||||
Expressions, MappingRegions);
|
||||
|
@ -277,9 +277,9 @@ pub fn create_dump_file<'tcx>(
|
||||
)
|
||||
})?;
|
||||
}
|
||||
Ok(fs::File::create_buffered(&file_path).map_err(|e| {
|
||||
fs::File::create_buffered(&file_path).map_err(|e| {
|
||||
io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}"))
|
||||
})?)
|
||||
})
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -281,7 +281,14 @@ impl<'tcx> Cx<'tcx> {
|
||||
.unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}"))
|
||||
.size;
|
||||
|
||||
let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap();
|
||||
let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
|
||||
if overflowing {
|
||||
// An erroneous enum with too many variants for its repr will emit E0081 and E0370
|
||||
self.tcx.dcx().span_delayed_bug(
|
||||
source.span,
|
||||
"overflowing enum wasn't rejected by hir analysis",
|
||||
);
|
||||
}
|
||||
let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
|
||||
let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
|
||||
|
||||
|
@ -363,7 +363,7 @@ fn calc_test_vectors_index(conditions: &mut Vec<MCDCBranch>) -> usize {
|
||||
let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info;
|
||||
[true_next_id, false_next_id]
|
||||
.into_iter()
|
||||
.filter_map(std::convert::identity)
|
||||
.flatten()
|
||||
.for_each(|next_id| indegree_stats[next_id] += 1);
|
||||
(condition_id, branch)
|
||||
})
|
||||
|
@ -87,7 +87,7 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
|
||||
covspans.retain(|covspan| {
|
||||
match covspan.expn_kind {
|
||||
// Retain only the first await-related or macro-expanded covspan with this span.
|
||||
Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => {
|
||||
Some(ExpnKind::Desugaring(DesugaringKind::Await)) => {
|
||||
deduplicated_spans.insert(covspan.span)
|
||||
}
|
||||
Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span),
|
||||
|
@ -2300,10 +2300,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
&mut diag,
|
||||
&cause,
|
||||
None,
|
||||
Some(ValuePairs::PolySigs(ExpectedFound {
|
||||
Some(param_env.and(ValuePairs::PolySigs(ExpectedFound {
|
||||
expected: ty::Binder::dummy(expected_sig),
|
||||
found: ty::Binder::dummy(sig),
|
||||
})),
|
||||
}))),
|
||||
terr,
|
||||
false,
|
||||
);
|
||||
|
@ -111,13 +111,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
|
||||
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
|
||||
// Unfortunately we cannot exhaustively list fields here, since the
|
||||
// struct is macro generated.
|
||||
// struct has private fields (to ensure its invariant is maintained)
|
||||
self.enabled_lang_features().hash_stable(hcx, hasher);
|
||||
self.enabled_lib_features().hash_stable(hcx, hasher);
|
||||
|
||||
// FIXME: why do we hash something that is a compile-time constant?
|
||||
for feature in rustc_feature::UNSTABLE_LANG_FEATURES.iter() {
|
||||
feature.name.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1133,6 +1133,7 @@ symbols! {
|
||||
lazy_normalization_consts,
|
||||
lazy_type_alias,
|
||||
le,
|
||||
legacy_receiver,
|
||||
len,
|
||||
let_chains,
|
||||
let_else,
|
||||
@ -1573,7 +1574,6 @@ symbols! {
|
||||
readonly,
|
||||
realloc,
|
||||
reason,
|
||||
receiver,
|
||||
recursion_limit,
|
||||
reexport_test_harness_main,
|
||||
ref_pat_eat_one_layer_2024,
|
||||
|
@ -21,6 +21,7 @@ pub(crate) fn target() -> Target {
|
||||
"-Vgcc_ntox86_cxx",
|
||||
]),
|
||||
env: "nto70".into(),
|
||||
vendor: "pc".into(),
|
||||
stack_probes: StackProbeType::Inline,
|
||||
..base::nto_qnx::opts()
|
||||
},
|
||||
|
@ -21,6 +21,7 @@ pub(crate) fn target() -> Target {
|
||||
"-Vgcc_ntox86_64_cxx",
|
||||
]),
|
||||
env: "nto71".into(),
|
||||
vendor: "pc".into(),
|
||||
..base::nto_qnx::opts()
|
||||
},
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
|
||||
use crate::infer;
|
||||
use crate::infer::relate::{self, RelateResult, TypeRelation};
|
||||
use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
|
||||
use crate::solve::deeply_normalize_for_diagnostics;
|
||||
use crate::traits::{
|
||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||
};
|
||||
@ -145,21 +146,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub fn report_mismatched_types(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::types(cause, true, expected, actual),
|
||||
param_env,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn report_mismatched_consts(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: ty::Const<'tcx>,
|
||||
actual: ty::Const<'tcx>,
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::consts(cause, true, expected, actual),
|
||||
param_env,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
@ -1133,7 +1144,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
diag: &mut Diag<'_>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
secondary_span: Option<(Span, Cow<'static, str>, bool)>,
|
||||
mut values: Option<ValuePairs<'tcx>>,
|
||||
mut values: Option<ty::ParamEnvAnd<'tcx, ValuePairs<'tcx>>>,
|
||||
terr: TypeError<'tcx>,
|
||||
prefer_label: bool,
|
||||
) {
|
||||
@ -1241,8 +1252,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
}
|
||||
let (expected_found, exp_found, is_simple_error, values) = match values {
|
||||
None => (None, Mismatch::Fixed("type"), false, None),
|
||||
Some(values) => {
|
||||
let values = self.resolve_vars_if_possible(values);
|
||||
Some(ty::ParamEnvAnd { param_env, value: values }) => {
|
||||
let mut values = self.resolve_vars_if_possible(values);
|
||||
if self.next_trait_solver() {
|
||||
values = deeply_normalize_for_diagnostics(self, param_env, values);
|
||||
}
|
||||
let (is_simple_error, exp_found) = match values {
|
||||
ValuePairs::Terms(ExpectedFound { expected, found }) => {
|
||||
match (expected.unpack(), found.unpack()) {
|
||||
@ -1773,6 +1787,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub fn report_and_explain_type_error(
|
||||
&self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||
@ -1784,7 +1799,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
self.type_error_additional_suggestions(&trace, terr),
|
||||
);
|
||||
let mut diag = self.dcx().create_err(failure_code);
|
||||
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false);
|
||||
self.note_type_err(
|
||||
&mut diag,
|
||||
&trace.cause,
|
||||
None,
|
||||
Some(param_env.and(trace.values)),
|
||||
terr,
|
||||
false,
|
||||
);
|
||||
diag
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
let mut err = match origin {
|
||||
infer::Subtype(box trace) => {
|
||||
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
|
||||
let mut err = self.report_and_explain_type_error(trace, terr);
|
||||
let mut err = self.report_and_explain_type_error(
|
||||
trace,
|
||||
self.tcx.param_env(generic_param_scope),
|
||||
terr,
|
||||
);
|
||||
match (*sub, *sup) {
|
||||
(ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
|
||||
(ty::RePlaceholder(_), _) => {
|
||||
@ -646,7 +650,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
}
|
||||
infer::Subtype(box trace) => {
|
||||
let terr = TypeError::RegionsPlaceholderMismatch;
|
||||
return self.report_and_explain_type_error(trace, terr);
|
||||
return self.report_and_explain_type_error(
|
||||
trace,
|
||||
self.tcx.param_env(generic_param_scope),
|
||||
terr,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return self.report_concrete_failure(
|
||||
|
@ -1290,7 +1290,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
(
|
||||
Some((
|
||||
data.projection_term,
|
||||
false,
|
||||
self.resolve_vars_if_possible(normalized_term),
|
||||
data.term,
|
||||
)),
|
||||
@ -1335,7 +1334,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
derive_better_type_error(lhs, rhs)
|
||||
{
|
||||
(
|
||||
Some((lhs, true, self.resolve_vars_if_possible(expected_term), rhs)),
|
||||
Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)),
|
||||
better_type_err,
|
||||
)
|
||||
} else if let Some(rhs) = rhs.to_alias_term()
|
||||
@ -1343,7 +1342,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
derive_better_type_error(rhs, lhs)
|
||||
{
|
||||
(
|
||||
Some((rhs, true, self.resolve_vars_if_possible(expected_term), lhs)),
|
||||
Some((rhs, self.resolve_vars_if_possible(expected_term), lhs)),
|
||||
better_type_err,
|
||||
)
|
||||
} else {
|
||||
@ -1354,7 +1353,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let msg = values
|
||||
.and_then(|(predicate, _, normalized_term, expected_term)| {
|
||||
.and_then(|(predicate, normalized_term, expected_term)| {
|
||||
self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
@ -1431,8 +1430,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
&mut diag,
|
||||
&obligation.cause,
|
||||
secondary_span,
|
||||
values.map(|(_, _, normalized_ty, expected_ty)| {
|
||||
infer::ValuePairs::Terms(ExpectedFound::new(true, expected_ty, normalized_ty))
|
||||
values.map(|(_, normalized_ty, expected_ty)| {
|
||||
obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new(
|
||||
true,
|
||||
expected_ty,
|
||||
normalized_ty,
|
||||
)))
|
||||
}),
|
||||
err,
|
||||
false,
|
||||
@ -2654,6 +2657,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
};
|
||||
self.report_and_explain_type_error(
|
||||
TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
|
||||
obligation.param_env,
|
||||
terr,
|
||||
)
|
||||
}
|
||||
@ -2744,6 +2748,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
{
|
||||
return Ok(self.report_and_explain_type_error(
|
||||
TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref),
|
||||
obligation.param_env,
|
||||
ty::error::TypeError::Mismatch,
|
||||
));
|
||||
}
|
||||
|
@ -287,6 +287,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
FulfillmentErrorCode::Subtype(ref expected_found, ref err) => self
|
||||
.report_mismatched_types(
|
||||
&error.obligation.cause,
|
||||
error.obligation.param_env,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
*err,
|
||||
@ -295,6 +296,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
FulfillmentErrorCode::ConstEquate(ref expected_found, ref err) => {
|
||||
let mut diag = self.report_mismatched_consts(
|
||||
&error.obligation.cause,
|
||||
error.obligation.param_env,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
*err,
|
||||
|
@ -196,7 +196,7 @@ use core::marker::{Tuple, Unsize};
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{
|
||||
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
|
||||
DerefPure, DispatchFromDyn, Receiver,
|
||||
DerefPure, DispatchFromDyn, LegacyReceiver,
|
||||
};
|
||||
use core::pin::{Pin, PinCoerceUnsized};
|
||||
use core::ptr::{self, NonNull, Unique};
|
||||
@ -2378,8 +2378,8 @@ impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Box<T, A> {}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized, A: Allocator> Receiver for Box<T, A> {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator + ?Sized, A: Allocator> Iterator for Box<I, A> {
|
||||
|
@ -129,6 +129,7 @@
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_next_chunk)]
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(legacy_receiver_trait)]
|
||||
#![feature(local_waker)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||
@ -138,7 +139,6 @@
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
#![feature(receiver_trait)]
|
||||
#![feature(set_ptr_value)]
|
||||
#![feature(sized_type_properties)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
|
@ -252,7 +252,7 @@ use core::intrinsics::abort;
|
||||
use core::iter;
|
||||
use core::marker::{PhantomData, Unsize};
|
||||
use core::mem::{self, ManuallyDrop, align_of_val_raw};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::pin::Pin;
|
||||
@ -2222,8 +2222,8 @@ unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> Receiver for Rc<T> {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for Rc<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc<T, A> {
|
||||
|
@ -18,7 +18,7 @@ use core::intrinsics::abort;
|
||||
use core::iter;
|
||||
use core::marker::{PhantomData, Unsize};
|
||||
use core::mem::{self, ManuallyDrop, align_of_val_raw};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
use core::pin::{Pin, PinCoerceUnsized};
|
||||
use core::ptr::{self, NonNull};
|
||||
@ -2189,8 +2189,8 @@ unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> Receiver for Arc<T> {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for Arc<T> {}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Arc<T, A> {
|
||||
|
@ -297,15 +297,21 @@ unsafe impl<T: ?Sized> DerefPure for &mut T {}
|
||||
/// Indicates that a struct can be used as a method receiver, without the
|
||||
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
|
||||
/// `Rc<T>`, `&T`, and `Pin<P>`.
|
||||
#[lang = "receiver"]
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
///
|
||||
/// This trait will shortly be removed and replaced with a more generic
|
||||
/// facility based around the current "arbitrary self types" unstable feature.
|
||||
/// That new facility will use a replacement trait called `Receiver` which is
|
||||
/// why this is now named `LegacyReceiver`.
|
||||
#[cfg_attr(bootstrap, lang = "receiver")]
|
||||
#[cfg_attr(not(bootstrap), lang = "legacy_receiver")]
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub trait Receiver {
|
||||
pub trait LegacyReceiver {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
|
@ -168,8 +168,8 @@ pub use self::control_flow::ControlFlow;
|
||||
pub use self::coroutine::{Coroutine, CoroutineState};
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
pub use self::deref::DerefPure;
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
pub use self::deref::Receiver;
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
pub use self::deref::LegacyReceiver;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::deref::{Deref, DerefMut};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -921,7 +921,7 @@
|
||||
#![stable(feature = "pin", since = "1.33.0")]
|
||||
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver};
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
|
||||
#[allow(unused_imports)]
|
||||
use crate::{
|
||||
cell::{RefCell, UnsafeCell},
|
||||
@ -1692,8 +1692,8 @@ impl<Ptr: DerefMut<Target: Unpin>> DerefMut for Pin<Ptr> {
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
unsafe impl<Ptr: DerefPure> DerefPure for Pin<Ptr> {}
|
||||
|
||||
#[unstable(feature = "receiver_trait", issue = "none")]
|
||||
impl<Ptr: Receiver> Receiver for Pin<Ptr> {}
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<Ptr: LegacyReceiver> LegacyReceiver for Pin<Ptr> {}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
|
||||
|
@ -376,6 +376,7 @@ pub struct Config {
|
||||
pub only_modified: bool,
|
||||
|
||||
pub target_cfgs: OnceLock<TargetCfgs>,
|
||||
pub builtin_cfg_names: OnceLock<HashSet<String>>,
|
||||
|
||||
pub nocapture: bool,
|
||||
|
||||
@ -443,6 +444,11 @@ impl Config {
|
||||
self.target_cfg().panic == PanicStrategy::Unwind
|
||||
}
|
||||
|
||||
/// Get the list of builtin, 'well known' cfg names
|
||||
pub fn builtin_cfg_names(&self) -> &HashSet<String> {
|
||||
self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self))
|
||||
}
|
||||
|
||||
pub fn has_threads(&self) -> bool {
|
||||
// Wasm targets don't have threads unless `-threads` is in the target
|
||||
// name, such as `wasm32-wasip1-threads`.
|
||||
@ -654,6 +660,18 @@ pub enum Endian {
|
||||
Big,
|
||||
}
|
||||
|
||||
fn builtin_cfg_names(config: &Config) -> HashSet<String> {
|
||||
rustc_output(
|
||||
config,
|
||||
&["--print=check-cfg", "-Zunstable-options", "--check-cfg=cfg()"],
|
||||
Default::default(),
|
||||
)
|
||||
.lines()
|
||||
.map(|l| if let Some((name, _)) = l.split_once('=') { name.to_string() } else { l.to_string() })
|
||||
.chain(std::iter::once(String::from("test")))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
|
||||
let mut command = Command::new(&config.rustc_path);
|
||||
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
|
||||
|
@ -362,6 +362,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
force_rerun: matches.opt_present("force-rerun"),
|
||||
|
||||
target_cfgs: OnceLock::new(),
|
||||
builtin_cfg_names: OnceLock::new(),
|
||||
|
||||
nocapture: matches.opt_present("nocapture"),
|
||||
|
||||
|
@ -478,6 +478,9 @@ impl<'test> TestCx<'test> {
|
||||
"error: redundant cfg argument `{normalized_revision}` is already created by the revision"
|
||||
);
|
||||
}
|
||||
if self.config.builtin_cfg_names().contains(&normalized_revision) {
|
||||
panic!("error: revision `{normalized_revision}` collides with a builtin cfg");
|
||||
}
|
||||
cmd.args(cfg_arg);
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ pub trait Sized {}
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
#[lang = "tuple_trait"]
|
||||
pub trait Tuple {}
|
||||
|
||||
|
@ -16,8 +16,8 @@ trait Sized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {}
|
||||
#[lang = "dispatch_from_dyn"]
|
||||
trait DispatchFromDyn<T> {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
|
@ -4,8 +4,8 @@
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
|
||||
pub auto trait Bar {}
|
||||
|
||||
|
@ -79,10 +79,10 @@ mod prelude {
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver {}
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy: Sized {}
|
||||
|
21
tests/ui/cast/ptr-to-trait-obj-drop-principal.rs
Normal file
21
tests/ui/cast/ptr-to-trait-obj-drop-principal.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//! Test that non-coercion casts aren't allowed to drop the principal,
|
||||
//! because they cannot modify the pointer metadata.
|
||||
//!
|
||||
//! We test this in a const context to guard against UB if this is allowed
|
||||
//! in the future.
|
||||
|
||||
trait Trait {}
|
||||
impl Trait for () {}
|
||||
|
||||
struct Wrapper<T: ?Sized>(T);
|
||||
|
||||
const OBJECT: *const (dyn Trait + Send) = &();
|
||||
|
||||
// coercions are allowed
|
||||
const _: *const dyn Send = OBJECT as _;
|
||||
|
||||
// casts are **not** allowed
|
||||
const _: *const Wrapper<dyn Send> = OBJECT as _;
|
||||
//~^ ERROR casting `*const (dyn Trait + Send + 'static)` as `*const Wrapper<dyn Send>` is invalid
|
||||
|
||||
fn main() {}
|
11
tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr
Normal file
11
tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0606]: casting `*const (dyn Trait + Send + 'static)` as `*const Wrapper<dyn Send>` is invalid
|
||||
--> $DIR/ptr-to-trait-obj-drop-principal.rs:18:37
|
||||
|
|
||||
LL | const _: *const Wrapper<dyn Send> = OBJECT as _;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: the trait objects may have different vtables
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0606`.
|
@ -50,5 +50,47 @@ enum MultipleDuplicates {
|
||||
//~^ NOTE `-2` assigned here
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Test for #131902
|
||||
// Ensure that casting an enum with too many variants for its repr
|
||||
// does not ICE
|
||||
#[repr(u8)]
|
||||
enum TooManyVariants {
|
||||
//~^ ERROR discriminant value `0` assigned more than once
|
||||
X000, X001, X002, X003, X004, X005, X006, X007, X008, X009,
|
||||
//~^ NOTE `0` assigned here
|
||||
//~| NOTE discriminant for `X256` incremented from this startpoint
|
||||
X010, X011, X012, X013, X014, X015, X016, X017, X018, X019,
|
||||
X020, X021, X022, X023, X024, X025, X026, X027, X028, X029,
|
||||
X030, X031, X032, X033, X034, X035, X036, X037, X038, X039,
|
||||
X040, X041, X042, X043, X044, X045, X046, X047, X048, X049,
|
||||
X050, X051, X052, X053, X054, X055, X056, X057, X058, X059,
|
||||
X060, X061, X062, X063, X064, X065, X066, X067, X068, X069,
|
||||
X070, X071, X072, X073, X074, X075, X076, X077, X078, X079,
|
||||
X080, X081, X082, X083, X084, X085, X086, X087, X088, X089,
|
||||
X090, X091, X092, X093, X094, X095, X096, X097, X098, X099,
|
||||
X100, X101, X102, X103, X104, X105, X106, X107, X108, X109,
|
||||
X110, X111, X112, X113, X114, X115, X116, X117, X118, X119,
|
||||
X120, X121, X122, X123, X124, X125, X126, X127, X128, X129,
|
||||
X130, X131, X132, X133, X134, X135, X136, X137, X138, X139,
|
||||
X140, X141, X142, X143, X144, X145, X146, X147, X148, X149,
|
||||
X150, X151, X152, X153, X154, X155, X156, X157, X158, X159,
|
||||
X160, X161, X162, X163, X164, X165, X166, X167, X168, X169,
|
||||
X170, X171, X172, X173, X174, X175, X176, X177, X178, X179,
|
||||
X180, X181, X182, X183, X184, X185, X186, X187, X188, X189,
|
||||
X190, X191, X192, X193, X194, X195, X196, X197, X198, X199,
|
||||
X200, X201, X202, X203, X204, X205, X206, X207, X208, X209,
|
||||
X210, X211, X212, X213, X214, X215, X216, X217, X218, X219,
|
||||
X220, X221, X222, X223, X224, X225, X226, X227, X228, X229,
|
||||
X230, X231, X232, X233, X234, X235, X236, X237, X238, X239,
|
||||
X240, X241, X242, X243, X244, X245, X246, X247, X248, X249,
|
||||
X250, X251, X252, X253, X254, X255,
|
||||
X256,
|
||||
//~^ ERROR enum discriminant overflowed
|
||||
//~| NOTE overflowed on value after 255
|
||||
//~| NOTE explicitly set `X256 = 0`
|
||||
//~| NOTE `0` assigned here
|
||||
}
|
||||
|
||||
fn main() {
|
||||
TooManyVariants::X256 as u8;
|
||||
}
|
||||
|
@ -73,6 +73,30 @@ LL |
|
||||
LL | V9,
|
||||
| -- `-2` assigned here
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0370]: enum discriminant overflowed
|
||||
--> $DIR/E0081.rs:87:5
|
||||
|
|
||||
LL | X256,
|
||||
| ^^^^ overflowed on value after 255
|
||||
|
|
||||
= note: explicitly set `X256 = 0` if that is desired outcome
|
||||
|
||||
For more information about this error, try `rustc --explain E0081`.
|
||||
error[E0081]: discriminant value `0` assigned more than once
|
||||
--> $DIR/E0081.rs:57:1
|
||||
|
|
||||
LL | enum TooManyVariants {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | X000, X001, X002, X003, X004, X005, X006, X007, X008, X009,
|
||||
| ----
|
||||
| |
|
||||
| `0` assigned here
|
||||
| discriminant for `X256` incremented from this startpoint (`X000` + 256 variants later => `X256` = 0)
|
||||
...
|
||||
LL | X256,
|
||||
| ---- `0` assigned here
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0081, E0370.
|
||||
For more information about an error, try `rustc --explain E0081`.
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Make sure that `#[expect(missing_docs)]` is always correctly fulfilled.
|
||||
|
||||
//@ check-pass
|
||||
//@ revisions: lib bin test
|
||||
//@ revisions: lib bin test_
|
||||
//@ [lib]compile-flags: --crate-type lib
|
||||
//@ [bin]compile-flags: --crate-type bin
|
||||
//@ [test]compile-flags: --test
|
||||
//@ [test_]compile-flags: --test
|
||||
|
||||
#[expect(missing_docs)]
|
||||
pub fn foo() {}
|
||||
|
@ -12,14 +12,14 @@ pub trait Deref {
|
||||
type Target;
|
||||
}
|
||||
|
||||
#[lang="receiver"]
|
||||
pub trait Receiver: Deref {}
|
||||
#[lang="legacy_receiver"]
|
||||
pub trait LegacyReceiver: Deref {}
|
||||
|
||||
impl<'a, T> Deref for &'a T {
|
||||
type Target = T;
|
||||
}
|
||||
|
||||
impl<'a, T> Receiver for &'a T {}
|
||||
impl<'a, T> LegacyReceiver for &'a T {}
|
||||
|
||||
mod bar {
|
||||
// shouldn't bring in too much
|
||||
|
@ -82,12 +82,12 @@ trait Copy {}
|
||||
#[lang = "tuple_trait"]
|
||||
trait Tuple {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
|
||||
#[stable(feature = "minicore", since = "1.0.0")]
|
||||
pub mod effects {
|
||||
|
@ -137,12 +137,12 @@ macro_rules! impl_fn_mut_tuple {
|
||||
//impl_fn_mut_tuple!(A B C D);
|
||||
//impl_fn_mut_tuple!(A B C D E);
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {}
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
|
||||
impl<T: ?Sized> Receiver for &mut T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
|
||||
#[lang = "destruct"]
|
||||
#[const_trait]
|
||||
@ -454,7 +454,7 @@ impl<T> /* const */ Deref for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Receiver> Receiver for Pin<P> {}
|
||||
impl<P: LegacyReceiver> LegacyReceiver for Pin<P> {}
|
||||
|
||||
impl<T: Clone> Clone for RefCell<T> {
|
||||
fn clone(&self) -> RefCell<T> {
|
||||
|
@ -0,0 +1,17 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// Make sure we try to mention a deeply normalized type in a type mismatch error.
|
||||
|
||||
trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T> Mirror for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
fn needs<T>(_: <T as Mirror>::Assoc) {}
|
||||
|
||||
fn main() {
|
||||
needs::<i32>(());
|
||||
//~^ ERROR mismatched types
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/deeply-normalize-type-expectation.rs:15:18
|
||||
|
|
||||
LL | needs::<i32>(());
|
||||
| ------------ ^^ expected `i32`, found `()`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/deeply-normalize-type-expectation.rs:12:4
|
||||
|
|
||||
LL | fn needs<T>(_: <T as Mirror>::Assoc) {}
|
||||
| ^^^^^ -----------------------
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
6
tests/ui/unpretty/extern-static.rs
Normal file
6
tests/ui/unpretty/extern-static.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//@ compile-flags: -Zunpretty=normal
|
||||
//@ check-pass
|
||||
|
||||
unsafe extern "C" {
|
||||
pub unsafe static STATIC: ();
|
||||
}
|
6
tests/ui/unpretty/extern-static.stdout
Normal file
6
tests/ui/unpretty/extern-static.stdout
Normal file
@ -0,0 +1,6 @@
|
||||
//@ compile-flags: -Zunpretty=normal
|
||||
//@ check-pass
|
||||
|
||||
unsafe extern "C" {
|
||||
pub unsafe static STATIC: ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user