Auto merge of #97315 - Dylan-DPC:rollup-2wee2oz, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - #96129 (Document rounding for floating-point primitive operations and string parsing) - #97286 (Add new eslint rule to prevent whitespace before function call paren) - #97292 (Lifetime variance fixes for rustc) - #97309 (Add some regression tests for #90400) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7f997f589f
|
@ -1,5 +1,6 @@
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use rustc_const_eval::util::CallKind;
|
use rustc_const_eval::util::CallKind;
|
||||||
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -1622,10 +1623,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
location: Location,
|
location: Location,
|
||||||
mpi: MovePathIndex,
|
mpi: MovePathIndex,
|
||||||
) -> (Vec<MoveSite>, Vec<Location>) {
|
) -> (Vec<MoveSite>, Vec<Location>) {
|
||||||
fn predecessor_locations<'a>(
|
fn predecessor_locations<'tcx, 'a>(
|
||||||
body: &'a mir::Body<'_>,
|
body: &'a mir::Body<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> impl Iterator<Item = Location> + 'a {
|
) -> impl Iterator<Item = Location> + Captures<'tcx> + 'a {
|
||||||
if location.statement_index == 0 {
|
if location.statement_index == 0 {
|
||||||
let predecessors = body.predecessors()[location.block].to_vec();
|
let predecessors = body.predecessors()[location.block].to_vec();
|
||||||
Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb)))
|
Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb)))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::infer::MemberConstraint;
|
use rustc_middle::infer::MemberConstraint;
|
||||||
|
@ -140,11 +141,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> MemberConstraintSet<'_, R>
|
impl<'tcx, R> MemberConstraintSet<'tcx, R>
|
||||||
where
|
where
|
||||||
R: Copy + Hash + Eq,
|
R: Copy + Hash + Eq,
|
||||||
{
|
{
|
||||||
pub(crate) fn all_indices(&self) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
|
pub(crate) fn all_indices(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = NllMemberConstraintIndex> + Captures<'tcx> + '_ {
|
||||||
self.constraints.indices()
|
self.constraints.indices()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +157,7 @@ where
|
||||||
pub(crate) fn indices(
|
pub(crate) fn indices(
|
||||||
&self,
|
&self,
|
||||||
member_region_vid: R,
|
member_region_vid: R,
|
||||||
) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
|
) -> impl Iterator<Item = NllMemberConstraintIndex> + Captures<'tcx> + '_ {
|
||||||
let mut next = self.first_constraints.get(&member_region_vid).cloned();
|
let mut next = self.first_constraints.get(&member_region_vid).cloned();
|
||||||
std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
|
std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
|
||||||
if let Some(current) = next {
|
if let Some(current) = next {
|
||||||
|
|
|
@ -10,17 +10,17 @@ use super::TypeChecker;
|
||||||
type VarPointRelation = Vec<(Local, LocationIndex)>;
|
type VarPointRelation = Vec<(Local, LocationIndex)>;
|
||||||
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
|
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
|
||||||
|
|
||||||
struct UseFactsExtractor<'me> {
|
struct UseFactsExtractor<'me, 'tcx> {
|
||||||
var_defined_at: &'me mut VarPointRelation,
|
var_defined_at: &'me mut VarPointRelation,
|
||||||
var_used_at: &'me mut VarPointRelation,
|
var_used_at: &'me mut VarPointRelation,
|
||||||
location_table: &'me LocationTable,
|
location_table: &'me LocationTable,
|
||||||
var_dropped_at: &'me mut VarPointRelation,
|
var_dropped_at: &'me mut VarPointRelation,
|
||||||
move_data: &'me MoveData<'me>,
|
move_data: &'me MoveData<'tcx>,
|
||||||
path_accessed_at_base: &'me mut PathPointRelation,
|
path_accessed_at_base: &'me mut PathPointRelation,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Visitor to walk through the MIR and extract point-wise facts
|
// A Visitor to walk through the MIR and extract point-wise facts
|
||||||
impl UseFactsExtractor<'_> {
|
impl UseFactsExtractor<'_, '_> {
|
||||||
fn location_to_index(&self, location: Location) -> LocationIndex {
|
fn location_to_index(&self, location: Location) -> LocationIndex {
|
||||||
self.location_table.mid_index(location)
|
self.location_table.mid_index(location)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitor<'_> for UseFactsExtractor<'_> {
|
impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> {
|
||||||
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
|
||||||
match def_use::categorize(context) {
|
match def_use::categorize(context) {
|
||||||
Some(DefUse::Def) => self.insert_def(local, location),
|
Some(DefUse::Def) => self.insert_def(local, location),
|
||||||
|
@ -63,7 +63,7 @@ impl Visitor<'_> for UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) {
|
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||||
self.super_place(place, context, location);
|
self.super_place(place, context, location);
|
||||||
match context {
|
match context {
|
||||||
PlaceContext::NonMutatingUse(_) => {
|
PlaceContext::NonMutatingUse(_) => {
|
||||||
|
@ -82,11 +82,11 @@ impl Visitor<'_> for UseFactsExtractor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn populate_access_facts<'tcx>(
|
pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'a, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
location_table: &LocationTable,
|
location_table: &LocationTable,
|
||||||
move_data: &MoveData<'_>,
|
move_data: &MoveData<'tcx>,
|
||||||
dropped_at: &mut Vec<(Local, Location)>,
|
dropped_at: &mut Vec<(Local, Location)>,
|
||||||
) {
|
) {
|
||||||
debug!("populate_access_facts()");
|
debug!("populate_access_facts()");
|
||||||
|
|
|
@ -197,7 +197,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
size: Size,
|
size: Size,
|
||||||
align: Align,
|
align: Align,
|
||||||
kind: MemoryKind<M::MemoryKind>,
|
kind: MemoryKind<M::MemoryKind>,
|
||||||
) -> InterpResult<'static, Pointer<M::PointerTag>> {
|
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
||||||
let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
|
let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
|
||||||
Ok(self.allocate_raw_ptr(alloc, kind))
|
Ok(self.allocate_raw_ptr(alloc, kind))
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
msg: CheckInAllocMsg,
|
msg: CheckInAllocMsg,
|
||||||
alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>,
|
alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>,
|
||||||
) -> InterpResult<'tcx, Option<T>> {
|
) -> InterpResult<'tcx, Option<T>> {
|
||||||
fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
|
fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
|
||||||
if offset % align.bytes() == 0 {
|
if offset % align.bytes() == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -654,7 +654,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
&self,
|
&self,
|
||||||
id: AllocId,
|
id: AllocId,
|
||||||
liveness: AllocCheck,
|
liveness: AllocCheck,
|
||||||
) -> InterpResult<'static, (Size, Align)> {
|
) -> InterpResult<'tcx, (Size, Align)> {
|
||||||
// # Regular allocations
|
// # Regular allocations
|
||||||
// Don't use `self.get_raw` here as that will
|
// Don't use `self.get_raw` here as that will
|
||||||
// a) cause cycles in case `id` refers to a static
|
// a) cause cycles in case `id` refers to a static
|
||||||
|
|
|
@ -1011,7 +1011,7 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
kind: MemoryKind<M::MemoryKind>,
|
kind: MemoryKind<M::MemoryKind>,
|
||||||
) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?;
|
let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?;
|
||||||
Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout))
|
Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout))
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
anon_region: Region<'tcx>,
|
anon_region: Region<'tcx>,
|
||||||
replace_region: Region<'tcx>,
|
replace_region: Region<'tcx>,
|
||||||
) -> Option<AnonymousParamInfo<'_>> {
|
) -> Option<AnonymousParamInfo<'tcx>> {
|
||||||
find_param_with_region(self.tcx(), anon_region, replace_region)
|
find_param_with_region(self.tcx(), anon_region, replace_region)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ impl<Tag> Allocation<Tag> {
|
||||||
|
|
||||||
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
|
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
|
||||||
/// available to the compiler to do so.
|
/// available to the compiler to do so.
|
||||||
pub fn uninit(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'static, Self> {
|
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
|
||||||
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
|
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
|
||||||
// This results in an error that can happen non-deterministically, since the memory
|
// This results in an error that can happen non-deterministically, since the memory
|
||||||
// available to the compiler can change between runs. Normally queries are always
|
// available to the compiler can change between runs. Normally queries are always
|
||||||
|
|
|
@ -397,38 +397,38 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
|
||||||
/// Converts the scalar to produce an unsigned integer of the given size.
|
/// Converts the scalar to produce an unsigned integer of the given size.
|
||||||
/// Fails if the scalar is a pointer.
|
/// Fails if the scalar is a pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_uint(self, size: Size) -> InterpResult<'static, u128> {
|
pub fn to_uint(self, size: Size) -> InterpResult<'tcx, u128> {
|
||||||
self.to_bits(size)
|
self.to_bits(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a `u8`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce a `u8`. Fails if the scalar is a pointer.
|
||||||
pub fn to_u8(self) -> InterpResult<'static, u8> {
|
pub fn to_u8(self) -> InterpResult<'tcx, u8> {
|
||||||
self.to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
|
self.to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a `u16`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce a `u16`. Fails if the scalar is a pointer.
|
||||||
pub fn to_u16(self) -> InterpResult<'static, u16> {
|
pub fn to_u16(self) -> InterpResult<'tcx, u16> {
|
||||||
self.to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
|
self.to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a `u32`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce a `u32`. Fails if the scalar is a pointer.
|
||||||
pub fn to_u32(self) -> InterpResult<'static, u32> {
|
pub fn to_u32(self) -> InterpResult<'tcx, u32> {
|
||||||
self.to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
|
self.to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a `u64`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce a `u64`. Fails if the scalar is a pointer.
|
||||||
pub fn to_u64(self) -> InterpResult<'static, u64> {
|
pub fn to_u64(self) -> InterpResult<'tcx, u64> {
|
||||||
self.to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
|
self.to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a `u128`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce a `u128`. Fails if the scalar is a pointer.
|
||||||
pub fn to_u128(self) -> InterpResult<'static, u128> {
|
pub fn to_u128(self) -> InterpResult<'tcx, u128> {
|
||||||
self.to_uint(Size::from_bits(128))
|
self.to_uint(Size::from_bits(128))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
|
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
|
||||||
/// Fails if the scalar is a pointer.
|
/// Fails if the scalar is a pointer.
|
||||||
pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'static, u64> {
|
pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
|
||||||
let b = self.to_uint(cx.data_layout().pointer_size)?;
|
let b = self.to_uint(cx.data_layout().pointer_size)?;
|
||||||
Ok(u64::try_from(b).unwrap())
|
Ok(u64::try_from(b).unwrap())
|
||||||
}
|
}
|
||||||
|
@ -436,51 +436,51 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
|
||||||
/// Converts the scalar to produce a signed integer of the given size.
|
/// Converts the scalar to produce a signed integer of the given size.
|
||||||
/// Fails if the scalar is a pointer.
|
/// Fails if the scalar is a pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_int(self, size: Size) -> InterpResult<'static, i128> {
|
pub fn to_int(self, size: Size) -> InterpResult<'tcx, i128> {
|
||||||
let b = self.to_bits(size)?;
|
let b = self.to_bits(size)?;
|
||||||
Ok(size.sign_extend(b) as i128)
|
Ok(size.sign_extend(b) as i128)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
|
||||||
pub fn to_i8(self) -> InterpResult<'static, i8> {
|
pub fn to_i8(self) -> InterpResult<'tcx, i8> {
|
||||||
self.to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
|
self.to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i16`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i16`. Fails if the scalar is a pointer.
|
||||||
pub fn to_i16(self) -> InterpResult<'static, i16> {
|
pub fn to_i16(self) -> InterpResult<'tcx, i16> {
|
||||||
self.to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
|
self.to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i32`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i32`. Fails if the scalar is a pointer.
|
||||||
pub fn to_i32(self) -> InterpResult<'static, i32> {
|
pub fn to_i32(self) -> InterpResult<'tcx, i32> {
|
||||||
self.to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
|
self.to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i64`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i64`. Fails if the scalar is a pointer.
|
||||||
pub fn to_i64(self) -> InterpResult<'static, i64> {
|
pub fn to_i64(self) -> InterpResult<'tcx, i64> {
|
||||||
self.to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
|
self.to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i128`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i128`. Fails if the scalar is a pointer.
|
||||||
pub fn to_i128(self) -> InterpResult<'static, i128> {
|
pub fn to_i128(self) -> InterpResult<'tcx, i128> {
|
||||||
self.to_int(Size::from_bits(128))
|
self.to_int(Size::from_bits(128))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce a machine-pointer-sized signed integer.
|
/// Converts the scalar to produce a machine-pointer-sized signed integer.
|
||||||
/// Fails if the scalar is a pointer.
|
/// Fails if the scalar is a pointer.
|
||||||
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
|
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
|
||||||
let b = self.to_int(cx.data_layout().pointer_size)?;
|
let b = self.to_int(cx.data_layout().pointer_size)?;
|
||||||
Ok(i64::try_from(b).unwrap())
|
Ok(i64::try_from(b).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_f32(self) -> InterpResult<'static, Single> {
|
pub fn to_f32(self) -> InterpResult<'tcx, Single> {
|
||||||
// Going through `u32` to check size and truncation.
|
// Going through `u32` to check size and truncation.
|
||||||
Ok(Single::from_bits(self.to_u32()?.into()))
|
Ok(Single::from_bits(self.to_u32()?.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_f64(self) -> InterpResult<'static, Double> {
|
pub fn to_f64(self) -> InterpResult<'tcx, Double> {
|
||||||
// Going through `u64` to check size and truncation.
|
// Going through `u64` to check size and truncation.
|
||||||
Ok(Double::from_bits(self.to_u64()?.into()))
|
Ok(Double::from_bits(self.to_u64()?.into()))
|
||||||
}
|
}
|
||||||
|
@ -534,7 +534,7 @@ impl<Tag> ScalarMaybeUninit<Tag> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_init(self) -> InterpResult<'static, Scalar<Tag>> {
|
pub fn check_init<'tcx>(self) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||||
match self {
|
match self {
|
||||||
ScalarMaybeUninit::Scalar(scalar) => Ok(scalar),
|
ScalarMaybeUninit::Scalar(scalar) => Ok(scalar),
|
||||||
ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)),
|
ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)),
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||||
use crate::ty::{self, List, Ty, TyCtxt};
|
use crate::ty::{self, List, Ty, TyCtxt};
|
||||||
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
|
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
|
||||||
|
|
||||||
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def::{CtorKind, Namespace};
|
use rustc_hir::def::{CtorKind, Namespace};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||||
|
@ -484,7 +485,7 @@ impl<'tcx> Body<'tcx> {
|
||||||
|
|
||||||
/// Returns an iterator over all user-declared mutable locals.
|
/// Returns an iterator over all user-declared mutable locals.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
|
pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
|
||||||
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
|
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
|
||||||
let local = Local::new(index);
|
let local = Local::new(index);
|
||||||
let decl = &self.local_decls[local];
|
let decl = &self.local_decls[local];
|
||||||
|
@ -498,7 +499,9 @@ impl<'tcx> Body<'tcx> {
|
||||||
|
|
||||||
/// Returns an iterator over all user-declared mutable arguments and locals.
|
/// Returns an iterator over all user-declared mutable arguments and locals.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
|
pub fn mut_vars_and_args_iter<'a>(
|
||||||
|
&'a self,
|
||||||
|
) -> impl Iterator<Item = Local> + Captures<'tcx> + 'a {
|
||||||
(1..self.local_decls.len()).filter_map(move |index| {
|
(1..self.local_decls.len()).filter_map(move |index| {
|
||||||
let local = Local::new(index);
|
let local = Local::new(index);
|
||||||
let decl = &self.local_decls[local];
|
let decl = &self.local_decls[local];
|
||||||
|
|
|
@ -192,7 +192,7 @@ impl<'tcx> MirPatch<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source_info_for_location(&self, body: &Body<'_>, loc: Location) -> SourceInfo {
|
pub fn source_info_for_location(&self, body: &Body<'tcx>, loc: Location) -> SourceInfo {
|
||||||
let data = match loc.block.index().checked_sub(body.basic_blocks().len()) {
|
let data = match loc.block.index().checked_sub(body.basic_blocks().len()) {
|
||||||
Some(new) => &self.new_blocks[new],
|
Some(new) => &self.new_blocks[new],
|
||||||
None => &body[loc.block],
|
None => &body[loc.block],
|
||||||
|
|
|
@ -115,8 +115,6 @@ impl Hash for ObligationCause<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation;
|
|
||||||
|
|
||||||
impl<'tcx> ObligationCause<'tcx> {
|
impl<'tcx> ObligationCause<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -201,7 +199,7 @@ pub struct UnifyReceiverContext<'tcx> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, Default)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, Default)]
|
||||||
pub struct InternedObligationCauseCode<'tcx> {
|
pub struct InternedObligationCauseCode<'tcx> {
|
||||||
/// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of
|
/// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
|
||||||
/// the time). `Some` otherwise.
|
/// the time). `Some` otherwise.
|
||||||
code: Option<Lrc<ObligationCauseCode<'tcx>>>,
|
code: Option<Lrc<ObligationCauseCode<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
@ -210,7 +208,11 @@ impl<'tcx> ObligationCauseCode<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn into(self) -> InternedObligationCauseCode<'tcx> {
|
fn into(self) -> InternedObligationCauseCode<'tcx> {
|
||||||
InternedObligationCauseCode {
|
InternedObligationCauseCode {
|
||||||
code: if let MISC_OBLIGATION_CAUSE_CODE = self { None } else { Some(Lrc::new(self)) },
|
code: if let ObligationCauseCode::MiscObligation = self {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Lrc::new(self))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +221,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
|
||||||
type Target = ObligationCauseCode<'tcx>;
|
type Target = ObligationCauseCode<'tcx>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE)
|
self.code.as_deref().unwrap_or(&ObligationCauseCode::MiscObligation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2163,7 +2163,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn same_size(self, other: SizeSkeleton<'_>) -> bool {
|
pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
|
(SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
|
||||||
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
|
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
|
||||||
|
|
|
@ -109,13 +109,13 @@ impl<'tcx> fmt::Debug for GenericArg<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Ord for GenericArg<'tcx> {
|
impl<'tcx> Ord for GenericArg<'tcx> {
|
||||||
fn cmp(&self, other: &GenericArg<'_>) -> Ordering {
|
fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
|
||||||
self.unpack().cmp(&other.unpack())
|
self.unpack().cmp(&other.unpack())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PartialOrd for GenericArg<'tcx> {
|
impl<'tcx> PartialOrd for GenericArg<'tcx> {
|
||||||
fn partial_cmp(&self, other: &GenericArg<'_>) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering> {
|
||||||
Some(self.cmp(&other))
|
Some(self.cmp(&other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
|
||||||
|
|
||||||
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
|
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
|
||||||
|
|
||||||
impl<'a, 'tcx> InternalSubsts<'tcx> {
|
impl<'tcx> InternalSubsts<'tcx> {
|
||||||
/// Checks whether all elements of this list are types, if so, transmute.
|
/// Checks whether all elements of this list are types, if so, transmute.
|
||||||
pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
|
pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
|
||||||
if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
|
if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
|
||||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
|
||||||
/// Closure substitutions have a particular structure controlled by the
|
/// Closure substitutions have a particular structure controlled by the
|
||||||
/// compiler that encodes information like the signature and closure kind;
|
/// compiler that encodes information like the signature and closure kind;
|
||||||
/// see `ty::ClosureSubsts` struct for more comments.
|
/// see `ty::ClosureSubsts` struct for more comments.
|
||||||
pub fn as_closure(&'a self) -> ClosureSubsts<'a> {
|
pub fn as_closure(&'tcx self) -> ClosureSubsts<'tcx> {
|
||||||
ClosureSubsts { substs: self }
|
ClosureSubsts { substs: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,20 +330,20 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
|
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
|
||||||
self.iter()
|
self.iter()
|
||||||
.filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None })
|
.filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn regions(&'a self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'a {
|
pub fn regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx {
|
||||||
self.iter().filter_map(|k| {
|
self.iter().filter_map(|k| {
|
||||||
if let GenericArgKind::Lifetime(lt) = k.unpack() { Some(lt) } else { None }
|
if let GenericArgKind::Lifetime(lt) = k.unpack() { Some(lt) } else { None }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'a {
|
pub fn consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx {
|
||||||
self.iter().filter_map(|k| {
|
self.iter().filter_map(|k| {
|
||||||
if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None }
|
if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None }
|
||||||
})
|
})
|
||||||
|
@ -351,8 +351,8 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn non_erasable_generics(
|
pub fn non_erasable_generics(
|
||||||
&'a self,
|
&'tcx self,
|
||||||
) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'a {
|
) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx {
|
||||||
self.iter().filter_map(|k| match k.unpack() {
|
self.iter().filter_map(|k| match k.unpack() {
|
||||||
GenericArgKind::Lifetime(_) => None,
|
GenericArgKind::Lifetime(_) => None,
|
||||||
generic => Some(generic),
|
generic => Some(generic),
|
||||||
|
|
|
@ -304,8 +304,8 @@ impl Direction for Backward {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
|
struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> {
|
||||||
body: &'a mir::Body<'a>,
|
body: &'a mir::Body<'tcx>,
|
||||||
pred: BasicBlock,
|
pred: BasicBlock,
|
||||||
exit_state: &'a mut D,
|
exit_state: &'a mut D,
|
||||||
bb: BasicBlock,
|
bb: BasicBlock,
|
||||||
|
@ -314,7 +314,7 @@ struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
|
||||||
effects_applied: bool,
|
effects_applied: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, D, F>
|
impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, '_, D, F>
|
||||||
where
|
where
|
||||||
D: Clone,
|
D: Clone,
|
||||||
F: FnMut(BasicBlock, &D),
|
F: FnMut(BasicBlock, &D),
|
||||||
|
|
|
@ -14,7 +14,7 @@ use super::*;
|
||||||
///
|
///
|
||||||
/// This is the `Body` that will be used by the `MockAnalysis` below. The shape of its CFG is not
|
/// This is the `Body` that will be used by the `MockAnalysis` below. The shape of its CFG is not
|
||||||
/// important.
|
/// important.
|
||||||
fn mock_body() -> mir::Body<'static> {
|
fn mock_body<'tcx>() -> mir::Body<'tcx> {
|
||||||
let source_info = mir::SourceInfo::outermost(DUMMY_SP);
|
let source_info = mir::SourceInfo::outermost(DUMMY_SP);
|
||||||
|
|
||||||
let mut blocks = IndexVec::new();
|
let mut blocks = IndexVec::new();
|
||||||
|
|
|
@ -481,8 +481,8 @@ impl std::fmt::Debug for BcbBranch {
|
||||||
// FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
|
// FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
|
||||||
// `catch_unwind()` handlers.
|
// `catch_unwind()` handlers.
|
||||||
fn bcb_filtered_successors<'a, 'tcx>(
|
fn bcb_filtered_successors<'a, 'tcx>(
|
||||||
body: &'tcx &'a mir::Body<'tcx>,
|
body: &'a mir::Body<'tcx>,
|
||||||
term_kind: &'tcx TerminatorKind<'tcx>,
|
term_kind: &'a TerminatorKind<'tcx>,
|
||||||
) -> Box<dyn Iterator<Item = BasicBlock> + 'a> {
|
) -> Box<dyn Iterator<Item = BasicBlock> + 'a> {
|
||||||
Box::new(
|
Box::new(
|
||||||
match &term_kind {
|
match &term_kind {
|
||||||
|
@ -691,12 +691,9 @@ pub(super) fn find_loop_backedges(
|
||||||
pub struct ShortCircuitPreorder<
|
pub struct ShortCircuitPreorder<
|
||||||
'a,
|
'a,
|
||||||
'tcx,
|
'tcx,
|
||||||
F: Fn(
|
F: Fn(&'a mir::Body<'tcx>, &'a TerminatorKind<'tcx>) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
||||||
&'tcx &'a mir::Body<'tcx>,
|
|
||||||
&'tcx TerminatorKind<'tcx>,
|
|
||||||
) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
|
||||||
> {
|
> {
|
||||||
body: &'tcx &'a mir::Body<'tcx>,
|
body: &'a mir::Body<'tcx>,
|
||||||
visited: BitSet<BasicBlock>,
|
visited: BitSet<BasicBlock>,
|
||||||
worklist: Vec<BasicBlock>,
|
worklist: Vec<BasicBlock>,
|
||||||
filtered_successors: F,
|
filtered_successors: F,
|
||||||
|
@ -705,14 +702,11 @@ pub struct ShortCircuitPreorder<
|
||||||
impl<
|
impl<
|
||||||
'a,
|
'a,
|
||||||
'tcx,
|
'tcx,
|
||||||
F: Fn(
|
F: Fn(&'a mir::Body<'tcx>, &'a TerminatorKind<'tcx>) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
||||||
&'tcx &'a mir::Body<'tcx>,
|
|
||||||
&'tcx TerminatorKind<'tcx>,
|
|
||||||
) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
|
||||||
> ShortCircuitPreorder<'a, 'tcx, F>
|
> ShortCircuitPreorder<'a, 'tcx, F>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
body: &'tcx &'a mir::Body<'tcx>,
|
body: &'a mir::Body<'tcx>,
|
||||||
filtered_successors: F,
|
filtered_successors: F,
|
||||||
) -> ShortCircuitPreorder<'a, 'tcx, F> {
|
) -> ShortCircuitPreorder<'a, 'tcx, F> {
|
||||||
let worklist = vec![mir::START_BLOCK];
|
let worklist = vec![mir::START_BLOCK];
|
||||||
|
@ -727,12 +721,9 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
'a: 'tcx,
|
'a,
|
||||||
'tcx,
|
'tcx,
|
||||||
F: Fn(
|
F: Fn(&'a mir::Body<'tcx>, &'a TerminatorKind<'tcx>) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
||||||
&'tcx &'a mir::Body<'tcx>,
|
|
||||||
&'tcx TerminatorKind<'tcx>,
|
|
||||||
) -> Box<dyn Iterator<Item = BasicBlock> + 'a>,
|
|
||||||
> Iterator for ShortCircuitPreorder<'a, 'tcx, F>
|
> Iterator for ShortCircuitPreorder<'a, 'tcx, F>
|
||||||
{
|
{
|
||||||
type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
|
type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
|
||||||
|
|
|
@ -98,7 +98,7 @@ fn object_safety_violations_for_trait(
|
||||||
span,
|
span,
|
||||||
) = violation
|
) = violation
|
||||||
{
|
{
|
||||||
lint_object_unsafe_trait(tcx, *span, trait_def_id, violation);
|
lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -278,7 +278,7 @@ fn predicate_references_self<'tcx>(
|
||||||
(predicate, sp): (ty::Predicate<'tcx>, Span),
|
(predicate, sp): (ty::Predicate<'tcx>, Span),
|
||||||
) -> Option<Span> {
|
) -> Option<Span> {
|
||||||
let self_ty = tcx.types.self_param;
|
let self_ty = tcx.types.self_param;
|
||||||
let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
|
let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into());
|
||||||
match predicate.kind().skip_binder() {
|
match predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::Trait(ref data) => {
|
ty::PredicateKind::Trait(ref data) => {
|
||||||
// In the case of a trait predicate, we can skip the "self" type.
|
// In the case of a trait predicate, we can skip the "self" type.
|
||||||
|
|
|
@ -961,7 +961,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> {
|
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> {
|
||||||
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
|
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
|
|
|
@ -1036,7 +1036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Special-case that coercion alone cannot handle:
|
// Special-case that coercion alone cannot handle:
|
||||||
// Function items or non-capturing closures of differing IDs or InternalSubsts.
|
// Function items or non-capturing closures of differing IDs or InternalSubsts.
|
||||||
let (a_sig, b_sig) = {
|
let (a_sig, b_sig) = {
|
||||||
let is_capturing_closure = |ty| {
|
#[allow(rustc::usage_of_ty_tykind)]
|
||||||
|
let is_capturing_closure = |ty: &ty::TyKind<'tcx>| {
|
||||||
if let &ty::Closure(closure_def_id, _substs) = ty {
|
if let &ty::Closure(closure_def_id, _substs) = ty {
|
||||||
self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some()
|
self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -959,7 +959,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Ideally this would be folded into the above, for uniform style
|
// Ideally this would be folded into the above, for uniform style
|
||||||
// but c-variadic is already a corner case
|
// but c-variadic is already a corner case
|
||||||
if c_variadic {
|
if c_variadic {
|
||||||
fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
|
fn variadic_error<'tcx>(
|
||||||
|
sess: &'tcx Session,
|
||||||
|
span: Span,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
cast_ty: &str,
|
||||||
|
) {
|
||||||
use crate::structured_errors::MissingCastForVariadicArg;
|
use crate::structured_errors::MissingCastForVariadicArg;
|
||||||
|
|
||||||
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
|
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
|
||||||
|
|
|
@ -2454,7 +2454,7 @@ fn trait_explicit_predicates_and_bounds(
|
||||||
gather_explicit_predicates_of(tcx, def_id.to_def_id())
|
gather_explicit_predicates_of(tcx, def_id.to_def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
fn explicit_predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||||
let def_kind = tcx.def_kind(def_id);
|
let def_kind = tcx.def_kind(def_id);
|
||||||
if let DefKind::Trait = def_kind {
|
if let DefKind::Trait = def_kind {
|
||||||
// Remove bounds on associated types from the predicates, they will be
|
// Remove bounds on associated types from the predicates, they will be
|
||||||
|
@ -2462,7 +2462,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||||
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
|
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
|
||||||
let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
|
|
||||||
let is_assoc_item_ty = |ty: Ty<'_>| {
|
let is_assoc_item_ty = |ty: Ty<'tcx>| {
|
||||||
// For a predicate from a where clause to become a bound on an
|
// For a predicate from a where clause to become a bound on an
|
||||||
// associated type:
|
// associated type:
|
||||||
// * It must use the identity substs of the item.
|
// * It must use the identity substs of the item.
|
||||||
|
|
|
@ -4,14 +4,14 @@ use rustc_middle::ty::{Ty, TypeFoldable};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
pub struct MissingCastForVariadicArg<'tcx> {
|
pub struct MissingCastForVariadicArg<'tcx, 's> {
|
||||||
pub sess: &'tcx Session,
|
pub sess: &'tcx Session,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
pub cast_ty: &'tcx str,
|
pub cast_ty: &'s str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
|
impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
|
||||||
fn session(&self) -> &Session {
|
fn session(&self) -> &Session {
|
||||||
self.sess
|
self.sess
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,8 +143,10 @@ macro_rules! from_str_float_impl {
|
||||||
/// # Return value
|
/// # Return value
|
||||||
///
|
///
|
||||||
/// `Err(ParseFloatError)` if the string did not represent a valid
|
/// `Err(ParseFloatError)` if the string did not represent a valid
|
||||||
/// number. Otherwise, `Ok(n)` where `n` is the floating-point
|
/// number. Otherwise, `Ok(n)` where `n` is the closest
|
||||||
/// number represented by `src`.
|
/// representable floating-point number to the number represented
|
||||||
|
/// by `src` (following the same rules for rounding as for the
|
||||||
|
/// results of primitive operations).
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
|
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
|
||||||
dec2flt(src)
|
dec2flt(src)
|
||||||
|
|
|
@ -994,6 +994,19 @@ mod prim_tuple {}
|
||||||
/// surprising results upon inspecting the bit patterns,
|
/// surprising results upon inspecting the bit patterns,
|
||||||
/// as the same calculations might produce NaNs with different bit patterns.
|
/// as the same calculations might produce NaNs with different bit patterns.
|
||||||
///
|
///
|
||||||
|
/// When the number resulting from a primitive operation (addition,
|
||||||
|
/// subtraction, multiplication, or division) on this type is not exactly
|
||||||
|
/// representable as `f32`, it is rounded according to the roundTiesToEven
|
||||||
|
/// direction defined in IEEE 754-2008. That means:
|
||||||
|
///
|
||||||
|
/// - The result is the representable value closest to the true value, if there
|
||||||
|
/// is a unique closest representable value.
|
||||||
|
/// - If the true value is exactly half-way between two representable values,
|
||||||
|
/// the result is the one with an even least-significant binary digit.
|
||||||
|
/// - If the true value's magnitude is ≥ `f32::MAX` + 2<sup>(`f32::MAX_EXP` −
|
||||||
|
/// `f32::MANTISSA_DIGITS` − 1)</sup>, the result is ∞ or −∞ (preserving the
|
||||||
|
/// true value's sign).
|
||||||
|
///
|
||||||
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
|
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
|
||||||
///
|
///
|
||||||
/// *[See also the `std::f32::consts` module](crate::f32::consts).*
|
/// *[See also the `std::f32::consts` module](crate::f32::consts).*
|
||||||
|
|
|
@ -994,6 +994,19 @@ mod prim_tuple {}
|
||||||
/// surprising results upon inspecting the bit patterns,
|
/// surprising results upon inspecting the bit patterns,
|
||||||
/// as the same calculations might produce NaNs with different bit patterns.
|
/// as the same calculations might produce NaNs with different bit patterns.
|
||||||
///
|
///
|
||||||
|
/// When the number resulting from a primitive operation (addition,
|
||||||
|
/// subtraction, multiplication, or division) on this type is not exactly
|
||||||
|
/// representable as `f32`, it is rounded according to the roundTiesToEven
|
||||||
|
/// direction defined in IEEE 754-2008. That means:
|
||||||
|
///
|
||||||
|
/// - The result is the representable value closest to the true value, if there
|
||||||
|
/// is a unique closest representable value.
|
||||||
|
/// - If the true value is exactly half-way between two representable values,
|
||||||
|
/// the result is the one with an even least-significant binary digit.
|
||||||
|
/// - If the true value's magnitude is ≥ `f32::MAX` + 2<sup>(`f32::MAX_EXP` −
|
||||||
|
/// `f32::MANTISSA_DIGITS` − 1)</sup>, the result is ∞ or −∞ (preserving the
|
||||||
|
/// true value's sign).
|
||||||
|
///
|
||||||
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
|
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
|
||||||
///
|
///
|
||||||
/// *[See also the `std::f32::consts` module](crate::f32::consts).*
|
/// *[See also the `std::f32::consts` module](crate::f32::consts).*
|
||||||
|
|
|
@ -46,5 +46,6 @@ module.exports = {
|
||||||
"error",
|
"error",
|
||||||
{ "beforeColon": false, "afterColon": true, "mode": "strict" }
|
{ "beforeColon": false, "afterColon": true, "mode": "strict" }
|
||||||
],
|
],
|
||||||
|
"func-call-spacing": ["error", "never"],
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
30
src/test/ui/type-alias-impl-trait/issue-90400-1.rs
Normal file
30
src/test/ui/type-alias-impl-trait/issue-90400-1.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Regression test for #90400,
|
||||||
|
// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn bar(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type FooFn<B>: FnOnce();
|
||||||
|
|
||||||
|
fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyFoo;
|
||||||
|
|
||||||
|
impl Foo for MyFoo {
|
||||||
|
type FooFn<B> = impl FnOnce();
|
||||||
|
|
||||||
|
fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
|
||||||
|
move || bar.bar() //~ ERROR: the trait bound `B: Bar` is not satisfied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let boom: <MyFoo as Foo>::FooFn<u32> = unsafe { core::mem::zeroed() };
|
||||||
|
boom();
|
||||||
|
}
|
19
src/test/ui/type-alias-impl-trait/issue-90400-1.stderr
Normal file
19
src/test/ui/type-alias-impl-trait/issue-90400-1.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0277]: the trait bound `B: Bar` is not satisfied
|
||||||
|
--> $DIR/issue-90400-1.rs:23:9
|
||||||
|
|
|
||||||
|
LL | move || bar.bar()
|
||||||
|
| ^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
||||||
|
|
|
||||||
|
note: required by a bound in `<MyFoo as Foo>::foo`
|
||||||
|
--> $DIR/issue-90400-1.rs:22:15
|
||||||
|
|
|
||||||
|
LL | fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
|
||||||
|
| ^^^ required by this bound in `<MyFoo as Foo>::foo`
|
||||||
|
help: consider restricting type parameter `B`
|
||||||
|
|
|
||||||
|
LL | type FooFn<B: Bar> = impl FnOnce();
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
38
src/test/ui/type-alias-impl-trait/issue-90400-2.rs
Normal file
38
src/test/ui/type-alias-impl-trait/issue-90400-2.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Regression test for #90400,
|
||||||
|
// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn bar(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Baz {
|
||||||
|
fn baz(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type FooFn<B>: Baz;
|
||||||
|
|
||||||
|
fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyFoo;
|
||||||
|
impl Foo for MyFoo {
|
||||||
|
type FooFn<B> = impl Baz;
|
||||||
|
|
||||||
|
fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
|
||||||
|
MyBaz(bar) //~ ERROR: the trait bound `B: Bar` is not satisfied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyBaz<B: Bar>(B);
|
||||||
|
impl<B: Bar> Baz for MyBaz<B> {
|
||||||
|
fn baz(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let boom: <MyFoo as Foo>::FooFn<u32> = unsafe { core::mem::zeroed() };
|
||||||
|
boom.baz();
|
||||||
|
}
|
19
src/test/ui/type-alias-impl-trait/issue-90400-2.stderr
Normal file
19
src/test/ui/type-alias-impl-trait/issue-90400-2.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0277]: the trait bound `B: Bar` is not satisfied
|
||||||
|
--> $DIR/issue-90400-2.rs:26:9
|
||||||
|
|
|
||||||
|
LL | MyBaz(bar)
|
||||||
|
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
||||||
|
|
|
||||||
|
note: required because of the requirements on the impl of `Baz` for `MyBaz<B>`
|
||||||
|
--> $DIR/issue-90400-2.rs:31:14
|
||||||
|
|
|
||||||
|
LL | impl<B: Bar> Baz for MyBaz<B> {
|
||||||
|
| ^^^ ^^^^^^^^
|
||||||
|
help: consider restricting type parameter `B`
|
||||||
|
|
|
||||||
|
LL | type FooFn<B: Bar> = impl Baz;
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in a new issue