commit
7db4177547
498 changed files with 8922 additions and 5897 deletions
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -11,6 +11,10 @@ name: CI
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
# CI on master only serves for caching citool builds for the `calculate_matrix` job.
|
||||
# In order to use GHA cache on PR CI (and auto/try) jobs, we need to write to it
|
||||
# from the default branch.
|
||||
- master
|
||||
- auto
|
||||
- try
|
||||
- try-perf
|
||||
|
|
@ -60,12 +64,18 @@ jobs:
|
|||
uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
||||
with:
|
||||
workspaces: src/ci/citool
|
||||
- name: Test citool
|
||||
# Only test citool on the auto branch, to reduce latency of the calculate matrix job
|
||||
# on PR/try builds.
|
||||
if: ${{ github.ref == 'refs/heads/auto' }}
|
||||
run: |
|
||||
cd src/ci/citool
|
||||
CARGO_INCREMENTAL=0 cargo test
|
||||
- name: Calculate the CI job matrix
|
||||
env:
|
||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||
run: |
|
||||
cd src/ci/citool
|
||||
CARGO_INCREMENTAL=0 cargo test
|
||||
CARGO_INCREMENTAL=0 cargo run calculate-job-matrix >> $GITHUB_OUTPUT
|
||||
id: jobs
|
||||
job:
|
||||
|
|
|
|||
54
Cargo.lock
54
Cargo.lock
|
|
@ -162,7 +162,7 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4"
|
||||
dependencies = [
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -235,7 +235,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
|
@ -2326,7 +2326,6 @@ dependencies = [
|
|||
"tempfile",
|
||||
"tikv-jemalloc-sys",
|
||||
"ui_test",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2509,7 +2508,19 @@ dependencies = [
|
|||
"indexmap",
|
||||
"memchr",
|
||||
"ruzstd",
|
||||
"wasmparser 0.222.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6273adb7096cf9ab4335f258e627d8230e69d40d45567d678f552dcec6245215"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"wasmparser 0.232.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3109,7 +3120,7 @@ dependencies = [
|
|||
"build_helper",
|
||||
"gimli",
|
||||
"libc",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"similar",
|
||||
|
|
@ -3118,11 +3129,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-build-sysroot"
|
||||
version = "0.5.7"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10edc2e4393515193bd766e2f6c050b0536a68e56f2b6d56c07ababfdc114ff0"
|
||||
checksum = "16d115ad7e26e0d1337f64ae6598f758194696afc2e9f34c8a6f24582529c3dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"tempfile",
|
||||
"walkdir",
|
||||
|
|
@ -3422,7 +3434,7 @@ dependencies = [
|
|||
"itertools",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object",
|
||||
"object 0.37.0",
|
||||
"rustc-demangle",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
|
|
@ -3463,7 +3475,7 @@ dependencies = [
|
|||
"either",
|
||||
"itertools",
|
||||
"libc",
|
||||
"object",
|
||||
"object 0.37.0",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"rustc_abi",
|
||||
|
|
@ -3640,6 +3652,7 @@ dependencies = [
|
|||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
"unic-langid",
|
||||
]
|
||||
|
|
@ -3786,6 +3799,7 @@ dependencies = [
|
|||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_trait_selection",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
|
|
@ -4495,7 +4509,7 @@ name = "rustc_target"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"object",
|
||||
"object 0.37.0",
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_fs_util",
|
||||
|
|
@ -5247,7 +5261,7 @@ checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1"
|
|||
dependencies = [
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
@ -5908,15 +5922,6 @@ dependencies = [
|
|||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.222.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa210fd1788e6b37a1d1930f3389c48e1d6ebd1a013d34fa4b7f9e3e3bf03146"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.229.0"
|
||||
|
|
@ -5941,6 +5946,15 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.232.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "917739b33bb1eb0e9a49bcd2637a351931be4578d0cc4d37b908d7a797784fbb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "230.0.0"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_index::bit_set::BitMatrix;
|
|||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
AbiAndPrefAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
|
||||
AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
|
||||
LayoutData, Niche, NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding,
|
||||
Variants, WrappingRange,
|
||||
};
|
||||
|
|
@ -173,13 +173,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
// Non-power-of-two vectors have padding up to the next power-of-two.
|
||||
// If we're a packed repr, remove the padding while keeping the alignment as close
|
||||
// to a vector as possible.
|
||||
(
|
||||
BackendRepr::Memory { sized: true },
|
||||
AbiAndPrefAlign {
|
||||
abi: Align::max_aligned_factor(size),
|
||||
pref: dl.llvmlike_vector_align(size).pref,
|
||||
},
|
||||
)
|
||||
(BackendRepr::Memory { sized: true }, AbiAlign { abi: Align::max_aligned_factor(size) })
|
||||
} else {
|
||||
(BackendRepr::SimdVector { element: e_repr, count }, dl.llvmlike_vector_align(size))
|
||||
};
|
||||
|
|
@ -435,13 +429,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
}
|
||||
|
||||
if let Some(pack) = repr.pack {
|
||||
align = align.min(AbiAndPrefAlign::new(pack));
|
||||
align = align.min(AbiAlign::new(pack));
|
||||
}
|
||||
// The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
|
||||
// See documentation on `LayoutS::unadjusted_abi_align`.
|
||||
let unadjusted_abi_align = align.abi;
|
||||
if let Some(repr_align) = repr.align {
|
||||
align = align.max(AbiAndPrefAlign::new(repr_align));
|
||||
align = align.max(AbiAlign::new(repr_align));
|
||||
}
|
||||
// `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate.
|
||||
let align = align;
|
||||
|
|
@ -1289,7 +1283,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
|
||||
let prefix_align =
|
||||
if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
|
||||
align = align.max(AbiAndPrefAlign::new(prefix_align));
|
||||
align = align.max(AbiAlign::new(prefix_align));
|
||||
offset = prefix_size.align_to(prefix_align);
|
||||
}
|
||||
for &i in &inverse_memory_index {
|
||||
|
|
@ -1308,7 +1302,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
|
||||
// Invariant: offset < dl.obj_size_bound() <= 1<<61
|
||||
let field_align = if let Some(pack) = pack {
|
||||
field.align.min(AbiAndPrefAlign::new(pack))
|
||||
field.align.min(AbiAlign::new(pack))
|
||||
} else {
|
||||
field.align
|
||||
};
|
||||
|
|
@ -1342,7 +1336,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
// See documentation on `LayoutS::unadjusted_abi_align`.
|
||||
let unadjusted_abi_align = align.abi;
|
||||
if let Some(repr_align) = repr.align {
|
||||
align = align.max(AbiAndPrefAlign::new(repr_align));
|
||||
align = align.max(AbiAlign::new(repr_align));
|
||||
}
|
||||
// `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate.
|
||||
let align = align;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_data_structures::intern::Interned;
|
|||
use rustc_macros::HashStable_Generic;
|
||||
|
||||
use crate::{
|
||||
AbiAndPrefAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
|
||||
AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
|
||||
PointeeInfo, Primitive, Scalar, Size, TargetDataLayout, Variants,
|
||||
};
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ impl<'a> Layout<'a> {
|
|||
self.0.0.largest_niche
|
||||
}
|
||||
|
||||
pub fn align(self) -> AbiAndPrefAlign {
|
||||
pub fn align(self) -> AbiAlign {
|
||||
self.0.0.align
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use std::fmt;
|
|||
#[cfg(feature = "nightly")]
|
||||
use std::iter::Step;
|
||||
use std::num::{NonZeroUsize, ParseIntError};
|
||||
use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
|
@ -226,22 +226,22 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct TargetDataLayout {
|
||||
pub endian: Endian,
|
||||
pub i1_align: AbiAndPrefAlign,
|
||||
pub i8_align: AbiAndPrefAlign,
|
||||
pub i16_align: AbiAndPrefAlign,
|
||||
pub i32_align: AbiAndPrefAlign,
|
||||
pub i64_align: AbiAndPrefAlign,
|
||||
pub i128_align: AbiAndPrefAlign,
|
||||
pub f16_align: AbiAndPrefAlign,
|
||||
pub f32_align: AbiAndPrefAlign,
|
||||
pub f64_align: AbiAndPrefAlign,
|
||||
pub f128_align: AbiAndPrefAlign,
|
||||
pub i1_align: AbiAlign,
|
||||
pub i8_align: AbiAlign,
|
||||
pub i16_align: AbiAlign,
|
||||
pub i32_align: AbiAlign,
|
||||
pub i64_align: AbiAlign,
|
||||
pub i128_align: AbiAlign,
|
||||
pub f16_align: AbiAlign,
|
||||
pub f32_align: AbiAlign,
|
||||
pub f64_align: AbiAlign,
|
||||
pub f128_align: AbiAlign,
|
||||
pub pointer_size: Size,
|
||||
pub pointer_align: AbiAndPrefAlign,
|
||||
pub aggregate_align: AbiAndPrefAlign,
|
||||
pub pointer_align: AbiAlign,
|
||||
pub aggregate_align: AbiAlign,
|
||||
|
||||
/// Alignments for vector types.
|
||||
pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
|
||||
pub vector_align: Vec<(Size, AbiAlign)>,
|
||||
|
||||
pub instruction_address_space: AddressSpace,
|
||||
|
||||
|
|
@ -257,22 +257,22 @@ impl Default for TargetDataLayout {
|
|||
let align = |bits| Align::from_bits(bits).unwrap();
|
||||
TargetDataLayout {
|
||||
endian: Endian::Big,
|
||||
i1_align: AbiAndPrefAlign::new(align(8)),
|
||||
i8_align: AbiAndPrefAlign::new(align(8)),
|
||||
i16_align: AbiAndPrefAlign::new(align(16)),
|
||||
i32_align: AbiAndPrefAlign::new(align(32)),
|
||||
i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
|
||||
i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
|
||||
f16_align: AbiAndPrefAlign::new(align(16)),
|
||||
f32_align: AbiAndPrefAlign::new(align(32)),
|
||||
f64_align: AbiAndPrefAlign::new(align(64)),
|
||||
f128_align: AbiAndPrefAlign::new(align(128)),
|
||||
i1_align: AbiAlign::new(align(8)),
|
||||
i8_align: AbiAlign::new(align(8)),
|
||||
i16_align: AbiAlign::new(align(16)),
|
||||
i32_align: AbiAlign::new(align(32)),
|
||||
i64_align: AbiAlign::new(align(32)),
|
||||
i128_align: AbiAlign::new(align(32)),
|
||||
f16_align: AbiAlign::new(align(16)),
|
||||
f32_align: AbiAlign::new(align(32)),
|
||||
f64_align: AbiAlign::new(align(64)),
|
||||
f128_align: AbiAlign::new(align(128)),
|
||||
pointer_size: Size::from_bits(64),
|
||||
pointer_align: AbiAndPrefAlign::new(align(64)),
|
||||
aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
|
||||
pointer_align: AbiAlign::new(align(64)),
|
||||
aggregate_align: AbiAlign { abi: align(8) },
|
||||
vector_align: vec![
|
||||
(Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
|
||||
(Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
|
||||
(Size::from_bits(64), AbiAlign::new(align(64))),
|
||||
(Size::from_bits(128), AbiAlign::new(align(128))),
|
||||
],
|
||||
instruction_address_space: AddressSpace::DATA,
|
||||
c_enum_min_size: Integer::I32,
|
||||
|
|
@ -330,8 +330,7 @@ impl TargetDataLayout {
|
|||
.map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
|
||||
};
|
||||
let abi = parse_bits(s[0], "alignment", cause)?;
|
||||
let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
|
||||
Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? })
|
||||
Ok(AbiAlign::new(align_from_bits(abi)?))
|
||||
};
|
||||
|
||||
let mut dl = TargetDataLayout::default();
|
||||
|
|
@ -426,7 +425,7 @@ impl TargetDataLayout {
|
|||
|
||||
/// psABI-mandated alignment for a vector type, if any
|
||||
#[inline]
|
||||
fn cabi_vector_align(&self, vec_size: Size) -> Option<AbiAndPrefAlign> {
|
||||
fn cabi_vector_align(&self, vec_size: Size) -> Option<AbiAlign> {
|
||||
self.vector_align
|
||||
.iter()
|
||||
.find(|(size, _align)| *size == vec_size)
|
||||
|
|
@ -435,8 +434,8 @@ impl TargetDataLayout {
|
|||
|
||||
/// an alignment resembling the one LLVM would pick for a vector
|
||||
#[inline]
|
||||
pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
|
||||
self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new(
|
||||
pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAlign {
|
||||
self.cabi_vector_align(vec_size).unwrap_or(AbiAlign::new(
|
||||
Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
|
||||
))
|
||||
}
|
||||
|
|
@ -864,25 +863,32 @@ impl Align {
|
|||
/// It is of effectively no consequence for layout in structs and on the stack.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||
pub struct AbiAndPrefAlign {
|
||||
pub struct AbiAlign {
|
||||
pub abi: Align,
|
||||
pub pref: Align,
|
||||
}
|
||||
|
||||
impl AbiAndPrefAlign {
|
||||
impl AbiAlign {
|
||||
#[inline]
|
||||
pub fn new(align: Align) -> AbiAndPrefAlign {
|
||||
AbiAndPrefAlign { abi: align, pref: align }
|
||||
pub fn new(align: Align) -> AbiAlign {
|
||||
AbiAlign { abi: align }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
|
||||
AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
|
||||
pub fn min(self, other: AbiAlign) -> AbiAlign {
|
||||
AbiAlign { abi: self.abi.min(other.abi) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
|
||||
AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
|
||||
pub fn max(self, other: AbiAlign) -> AbiAlign {
|
||||
AbiAlign { abi: self.abi.max(other.abi) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AbiAlign {
|
||||
type Target = Align;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.abi
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -945,7 +951,7 @@ impl Integer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
|
||||
use Integer::*;
|
||||
let dl = cx.data_layout();
|
||||
|
||||
|
|
@ -1058,7 +1064,7 @@ impl Float {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
|
||||
use Float::*;
|
||||
let dl = cx.data_layout();
|
||||
|
||||
|
|
@ -1102,7 +1108,7 @@ impl Primitive {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
||||
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
|
||||
use Primitive::*;
|
||||
let dl = cx.data_layout();
|
||||
|
||||
|
|
@ -1225,7 +1231,7 @@ impl Scalar {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
|
||||
pub fn align(self, cx: &impl HasDataLayout) -> AbiAlign {
|
||||
self.primitive().align(cx)
|
||||
}
|
||||
|
||||
|
|
@ -1731,7 +1737,7 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
|
|||
/// especially in the case of by-pointer struct returns, which allocate stack even when unused.
|
||||
pub uninhabited: bool,
|
||||
|
||||
pub align: AbiAndPrefAlign,
|
||||
pub align: AbiAlign,
|
||||
pub size: Size,
|
||||
|
||||
/// The largest alignment explicitly requested with `repr(align)` on this type or any field.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use std::ops::DerefMut;
|
|||
use std::panic;
|
||||
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Ident, Span};
|
||||
use smallvec::{Array, SmallVec, smallvec};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -19,7 +19,7 @@ use thin_vec::ThinVec;
|
|||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::*;
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit, visit_opt, walk_list};
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, VisitorResult, try_visit, visit_opt, walk_list};
|
||||
|
||||
pub trait ExpectOne<A: Array> {
|
||||
fn expect_one(self, err: &'static str) -> A::Item;
|
||||
|
|
@ -32,7 +32,22 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait MutVisitor: Sized {
|
||||
mod sealed {
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
|
||||
/// This is for compatibility with the regular `Visitor`.
|
||||
pub trait MutVisitorResult {
|
||||
type Result: VisitorResult;
|
||||
}
|
||||
|
||||
impl<T> MutVisitorResult for T {
|
||||
type Result = ();
|
||||
}
|
||||
}
|
||||
|
||||
use sealed::MutVisitorResult;
|
||||
|
||||
pub trait MutVisitor: Sized + MutVisitorResult<Result = ()> {
|
||||
// Methods in this trait have one of three forms:
|
||||
//
|
||||
// fn visit_t(&mut self, t: &mut T); // common
|
||||
|
|
@ -227,14 +242,6 @@ pub trait MutVisitor: Sized {
|
|||
walk_generic_args(self, p);
|
||||
}
|
||||
|
||||
fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) {
|
||||
walk_angle_bracketed_parameter_data(self, p);
|
||||
}
|
||||
|
||||
fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) {
|
||||
walk_parenthesized_parameter_data(self, p);
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &mut Local) {
|
||||
walk_local(self, l);
|
||||
}
|
||||
|
|
@ -303,10 +310,6 @@ pub trait MutVisitor: Sized {
|
|||
walk_flat_map_expr_field(self, f)
|
||||
}
|
||||
|
||||
fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
|
||||
walk_where_clause(self, where_clause);
|
||||
}
|
||||
|
||||
fn flat_map_where_predicate(
|
||||
&mut self,
|
||||
where_predicate: WherePredicate,
|
||||
|
|
@ -385,19 +388,14 @@ generate_flat_map_visitor_fns! {
|
|||
visit_generic_params, GenericParam, flat_map_generic_param;
|
||||
visit_stmts, Stmt, flat_map_stmt;
|
||||
visit_exprs, P<Expr>, filter_map_expr;
|
||||
visit_expr_fields, ExprField, flat_map_expr_field;
|
||||
visit_pat_fields, PatField, flat_map_pat_field;
|
||||
visit_variants, Variant, flat_map_variant;
|
||||
visit_assoc_items, P<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_vec<T, F>(elems: &mut Vec<T>, mut visit_elem: F)
|
||||
where
|
||||
F: FnMut(&mut T),
|
||||
{
|
||||
for elem in elems {
|
||||
visit_elem(elem);
|
||||
}
|
||||
visit_where_predicates, WherePredicate, flat_map_where_predicate;
|
||||
visit_params, Param, flat_map_param;
|
||||
visit_field_defs, FieldDef, flat_map_field_def;
|
||||
visit_arms, Arm, flat_map_arm;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -410,40 +408,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F)
|
||||
where
|
||||
F: FnMut(&mut T),
|
||||
{
|
||||
if let Some(elem) = opt {
|
||||
visit_elem(elem);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) {
|
||||
for attr in attrs.iter_mut() {
|
||||
vis.visit_attribute(attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
|
||||
match args {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(args) => visit_delim_args(vis, args),
|
||||
AttrArgs::Eq { eq_span, expr } => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_span(eq_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_delim_args<T: MutVisitor>(vis: &mut T, args: &mut DelimArgs) {
|
||||
let DelimArgs { dspan, delim: _, tokens: _ } = args;
|
||||
let DelimSpan { open, close } = dspan;
|
||||
vis.visit_span(open);
|
||||
vis.visit_span(close);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_pat_field<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
mut fp: PatField,
|
||||
|
|
@ -461,40 +431,11 @@ fn visit_nested_use_tree<V: MutVisitor>(
|
|||
vis.visit_use_tree(nested_tree);
|
||||
}
|
||||
|
||||
pub fn walk_arm<T: MutVisitor>(vis: &mut T, arm: &mut Arm) {
|
||||
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(vis, attrs);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(guard, |guard| vis.visit_expr(guard));
|
||||
visit_opt(body, |body| vis.visit_expr(body));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_arm<T: MutVisitor>(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> {
|
||||
vis.visit_arm(&mut arm);
|
||||
smallvec![arm]
|
||||
}
|
||||
|
||||
fn walk_assoc_item_constraint<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
if let Some(gen_args) = gen_args {
|
||||
vis.visit_generic_args(gen_args);
|
||||
}
|
||||
match kind {
|
||||
AssocItemConstraintKind::Equality { term } => match term {
|
||||
Term::Ty(ty) => vis.visit_ty(ty),
|
||||
Term::Const(c) => vis.visit_anon_const(c),
|
||||
},
|
||||
AssocItemConstraintKind::Bound { bounds } => visit_bounds(vis, bounds, BoundKind::Bound),
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_variant<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
mut variant: Variant,
|
||||
|
|
@ -503,64 +444,6 @@ pub fn walk_flat_map_variant<T: MutVisitor>(
|
|||
smallvec![variant]
|
||||
}
|
||||
|
||||
fn walk_generic_args<T: MutVisitor>(vis: &mut T, generic_args: &mut GenericArgs) {
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
|
||||
GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
|
||||
GenericArgs::ParenthesizedElided(span) => vis.visit_span(span),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_generic_arg<T: MutVisitor>(vis: &mut T, arg: &mut GenericArg) {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => vis.visit_lifetime(lt),
|
||||
GenericArg::Type(ty) => vis.visit_ty(ty),
|
||||
GenericArg::Const(ct) => vis.visit_anon_const(ct),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_angle_bracketed_parameter_data<T: MutVisitor>(vis: &mut T, data: &mut AngleBracketedArgs) {
|
||||
let AngleBracketedArgs { args, span } = data;
|
||||
visit_thin_vec(args, |arg| match arg {
|
||||
AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
|
||||
AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint),
|
||||
});
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut ParenthesizedArgs) {
|
||||
let ParenthesizedArgs { inputs, output, span, inputs_span } = args;
|
||||
visit_thin_vec(inputs, |input| vis.visit_ty(input));
|
||||
vis.visit_fn_ret_ty(output);
|
||||
vis.visit_span(span);
|
||||
vis.visit_span(inputs_span);
|
||||
}
|
||||
|
||||
fn walk_attribute<T: MutVisitor>(vis: &mut T, attr: &mut Attribute) {
|
||||
let Attribute { kind, id: _, style: _, span } = attr;
|
||||
match kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
let NormalAttr { item: AttrItem { unsafety: _, path, args, tokens: _ }, tokens: _ } =
|
||||
&mut **normal;
|
||||
vis.visit_path(path);
|
||||
visit_attr_args(vis, args);
|
||||
}
|
||||
AttrKind::DocComment(_kind, _sym) => {}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn walk_mac<T: MutVisitor>(vis: &mut T, mac: &mut MacCall) {
|
||||
let MacCall { path, args } = mac;
|
||||
vis.visit_path(path);
|
||||
visit_delim_args(vis, args);
|
||||
}
|
||||
|
||||
fn walk_macro_def<T: MutVisitor>(vis: &mut T, macro_def: &mut MacroDef) {
|
||||
let MacroDef { body, macro_rules: _ } = macro_def;
|
||||
visit_delim_args(vis, body);
|
||||
}
|
||||
|
||||
fn walk_meta_list_item<T: MutVisitor>(vis: &mut T, li: &mut MetaItemInner) {
|
||||
match li {
|
||||
MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi),
|
||||
|
|
@ -578,138 +461,11 @@ fn walk_meta_item<T: MutVisitor>(vis: &mut T, mi: &mut MetaItem) {
|
|||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_param<T: MutVisitor>(vis: &mut T, param: &mut Param) {
|
||||
let Param { attrs, id, pat, span, ty, is_placeholder: _ } = param;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(vis, attrs);
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_param<T: MutVisitor>(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> {
|
||||
vis.visit_param(&mut param);
|
||||
smallvec![param]
|
||||
}
|
||||
|
||||
fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
|
||||
match binder {
|
||||
ClosureBinder::NotPresent => {}
|
||||
ClosureBinder::For { span: _, generic_params } => {
|
||||
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
|
||||
match kind {
|
||||
FnKind::Fn(
|
||||
_ctxt,
|
||||
_vis,
|
||||
Fn {
|
||||
defaultness,
|
||||
ident,
|
||||
generics,
|
||||
contract,
|
||||
body,
|
||||
sig: FnSig { header, decl, span },
|
||||
define_opaque,
|
||||
},
|
||||
) => {
|
||||
// Visibility is visited as a part of the item.
|
||||
visit_defaultness(vis, defaultness);
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_fn_header(header);
|
||||
vis.visit_generics(generics);
|
||||
vis.visit_fn_decl(decl);
|
||||
if let Some(contract) = contract {
|
||||
vis.visit_contract(contract);
|
||||
}
|
||||
if let Some(body) = body {
|
||||
vis.visit_block(body);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
|
||||
walk_define_opaques(vis, define_opaque);
|
||||
}
|
||||
FnKind::Closure(binder, coroutine_kind, decl, body) => {
|
||||
vis.visit_closure_binder(binder);
|
||||
coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
|
||||
vis.visit_fn_decl(decl);
|
||||
vis.visit_expr(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut FnContract) {
|
||||
let FnContract { requires, ensures } = contract;
|
||||
if let Some(pred) = requires {
|
||||
vis.visit_expr(pred);
|
||||
}
|
||||
if let Some(pred) = ensures {
|
||||
vis.visit_expr(pred);
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut FnDecl) {
|
||||
let FnDecl { inputs, output } = decl;
|
||||
inputs.flat_map_in_place(|param| vis.flat_map_param(param));
|
||||
vis.visit_fn_ret_ty(output);
|
||||
}
|
||||
|
||||
fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) {
|
||||
match fn_ret_ty {
|
||||
FnRetTy::Default(span) => vis.visit_span(span),
|
||||
FnRetTy::Ty(ty) => vis.visit_ty(ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) {
|
||||
match pb {
|
||||
GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref),
|
||||
GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime),
|
||||
GenericBound::Use(args, span) => {
|
||||
for arg in args {
|
||||
vis.visit_precise_capturing_arg(arg);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_precise_capturing_arg<T: MutVisitor>(vis: &mut T, arg: &mut PreciseCapturingArg) {
|
||||
match arg {
|
||||
PreciseCapturingArg::Lifetime(lt) => {
|
||||
vis.visit_lifetime(lt);
|
||||
}
|
||||
PreciseCapturingArg::Arg(path, id) => {
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_generic_param<T: MutVisitor>(vis: &mut T, param: &mut GenericParam) {
|
||||
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = param;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(vis, attrs);
|
||||
vis.visit_ident(ident);
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
|
||||
match kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
GenericParamKind::Type { default } => {
|
||||
visit_opt(default, |default| vis.visit_ty(default));
|
||||
}
|
||||
GenericParamKind::Const { ty, kw_span: _, default } => {
|
||||
vis.visit_ty(ty);
|
||||
visit_opt(default, |default| vis.visit_anon_const(default));
|
||||
}
|
||||
}
|
||||
if let Some(colon_span) = colon_span {
|
||||
vis.visit_span(colon_span);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_generic_param<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
mut param: GenericParam,
|
||||
|
|
@ -718,13 +474,6 @@ pub fn walk_flat_map_generic_param<T: MutVisitor>(
|
|||
smallvec![param]
|
||||
}
|
||||
|
||||
fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) {
|
||||
let Generics { params, where_clause, span } = generics;
|
||||
params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
|
||||
vis.visit_where_clause(where_clause);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWhereClauses) {
|
||||
let TyAliasWhereClauses { before, after, split: _ } = tawcs;
|
||||
let TyAliasWhereClause { has_where_token: _, span: span_before } = before;
|
||||
|
|
@ -733,70 +482,14 @@ fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWh
|
|||
vis.visit_span(span_after);
|
||||
}
|
||||
|
||||
fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) {
|
||||
let WhereClause { has_where_token: _, predicates, span } = wc;
|
||||
predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_where_predicate<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
mut pred: WherePredicate,
|
||||
) -> SmallVec<[WherePredicate; 1]> {
|
||||
let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = &mut pred;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(vis, attrs);
|
||||
vis.visit_where_predicate_kind(kind);
|
||||
vis.visit_span(span);
|
||||
walk_where_predicate(vis, &mut pred);
|
||||
smallvec![pred]
|
||||
}
|
||||
|
||||
pub fn walk_where_predicate_kind<T: MutVisitor>(vis: &mut T, kind: &mut WherePredicateKind) {
|
||||
match kind {
|
||||
WherePredicateKind::BoundPredicate(bp) => {
|
||||
let WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } = bp;
|
||||
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
|
||||
vis.visit_ty(bounded_ty);
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
|
||||
}
|
||||
WherePredicateKind::RegionPredicate(rp) => {
|
||||
let WhereRegionPredicate { lifetime, bounds } = rp;
|
||||
vis.visit_lifetime(lifetime);
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
|
||||
}
|
||||
WherePredicateKind::EqPredicate(ep) => {
|
||||
let WhereEqPredicate { lhs_ty, rhs_ty } = ep;
|
||||
vis.visit_ty(lhs_ty);
|
||||
vis.visit_ty(rhs_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_variant_data<T: MutVisitor>(vis: &mut T, vdata: &mut VariantData) {
|
||||
match vdata {
|
||||
VariantData::Struct { fields, recovered: _ } => {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Tuple(fields, id) => {
|
||||
vis.visit_id(id);
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Unit(id) => vis.visit_id(id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_field_def<T: MutVisitor>(visitor: &mut T, fd: &mut FieldDef) {
|
||||
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd;
|
||||
visitor.visit_id(id);
|
||||
visit_attrs(visitor, attrs);
|
||||
visitor.visit_vis(vis);
|
||||
visit_safety(visitor, safety);
|
||||
visit_opt(ident, |ident| visitor.visit_ident(ident));
|
||||
visitor.visit_ty(ty);
|
||||
visit_opt(default, |default| visitor.visit_anon_const(default));
|
||||
visitor.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_flat_map_field_def<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
mut fd: FieldDef,
|
||||
|
|
@ -846,255 +539,6 @@ pub fn walk_flat_map_assoc_item(
|
|||
smallvec![item]
|
||||
}
|
||||
|
||||
fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
|
||||
// FIXME: Visit spans inside all this currently ignored stuff.
|
||||
let InlineAsm {
|
||||
asm_macro: _,
|
||||
template: _,
|
||||
template_strs: _,
|
||||
operands,
|
||||
clobber_abis: _,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
} = asm;
|
||||
for (op, span) in operands {
|
||||
match op {
|
||||
InlineAsmOperand::In { expr, reg: _ }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
|
||||
| InlineAsmOperand::InOut { expr, reg: _, late: _ } => vis.visit_expr(expr),
|
||||
InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
|
||||
vis.visit_expr(in_expr);
|
||||
if let Some(out_expr) = out_expr {
|
||||
vis.visit_expr(out_expr);
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
|
||||
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
|
||||
InlineAsmOperand::Label { block } => vis.visit_block(block),
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_inline_asm_sym<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
|
||||
fn walk_format_args<T: MutVisitor>(vis: &mut T, fmt: &mut FormatArgs) {
|
||||
// FIXME: visit the template exhaustively.
|
||||
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
|
||||
for FormatArgument { kind, expr } in arguments.all_args_mut() {
|
||||
match kind {
|
||||
FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
|
||||
vis.visit_ident(ident)
|
||||
}
|
||||
FormatArgumentKind::Normal => {}
|
||||
}
|
||||
vis.visit_expr(expr);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, tokens: _ }: &mut Expr) {
|
||||
vis.visit_id(id);
|
||||
visit_attrs(vis, attrs);
|
||||
match kind {
|
||||
ExprKind::Array(exprs) => visit_exprs(vis, exprs),
|
||||
ExprKind::ConstBlock(anon_const) => {
|
||||
vis.visit_anon_const(anon_const);
|
||||
}
|
||||
ExprKind::Repeat(expr, count) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_anon_const(count);
|
||||
}
|
||||
ExprKind::Tup(exprs) => visit_exprs(vis, exprs),
|
||||
ExprKind::Call(f, args) => {
|
||||
vis.visit_expr(f);
|
||||
visit_exprs(vis, args);
|
||||
}
|
||||
ExprKind::MethodCall(box MethodCall {
|
||||
seg: PathSegment { ident, id, args: seg_args },
|
||||
receiver,
|
||||
args: call_args,
|
||||
span,
|
||||
}) => {
|
||||
vis.visit_method_receiver_expr(receiver);
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(seg_args, |args| vis.visit_generic_args(args));
|
||||
visit_exprs(vis, call_args);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::Binary(binop, lhs, rhs) => {
|
||||
vis.visit_expr(lhs);
|
||||
vis.visit_expr(rhs);
|
||||
vis.visit_span(&mut binop.span);
|
||||
}
|
||||
ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
|
||||
ExprKind::Cast(expr, ty) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_ty(ty);
|
||||
}
|
||||
ExprKind::Type(expr, ty) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_ty(ty);
|
||||
}
|
||||
ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs),
|
||||
ExprKind::Let(pat, scrutinee, span, _recovered) => {
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_expr(scrutinee);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::If(cond, tr, fl) => {
|
||||
vis.visit_expr(cond);
|
||||
vis.visit_block(tr);
|
||||
visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl)));
|
||||
}
|
||||
ExprKind::While(cond, body, label) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_expr(cond);
|
||||
vis.visit_block(body);
|
||||
}
|
||||
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_expr(iter);
|
||||
vis.visit_block(body);
|
||||
}
|
||||
ExprKind::Loop(body, label, span) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_block(body);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::Match(expr, arms, _kind) => {
|
||||
vis.visit_expr(expr);
|
||||
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
|
||||
}
|
||||
ExprKind::Closure(box Closure {
|
||||
binder,
|
||||
capture_clause,
|
||||
constness,
|
||||
coroutine_kind,
|
||||
movability: _,
|
||||
fn_decl,
|
||||
body,
|
||||
fn_decl_span,
|
||||
fn_arg_span,
|
||||
}) => {
|
||||
visit_constness(vis, constness);
|
||||
vis.visit_capture_by(capture_clause);
|
||||
vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id);
|
||||
vis.visit_span(fn_decl_span);
|
||||
vis.visit_span(fn_arg_span);
|
||||
}
|
||||
ExprKind::Block(blk, label) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_block(blk);
|
||||
}
|
||||
ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
|
||||
vis.visit_block(body);
|
||||
vis.visit_span(decl_span);
|
||||
}
|
||||
ExprKind::Await(expr, await_kw_span) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_span(await_kw_span);
|
||||
}
|
||||
ExprKind::Use(expr, use_kw_span) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_span(use_kw_span);
|
||||
}
|
||||
ExprKind::Assign(el, er, span) => {
|
||||
vis.visit_expr(el);
|
||||
vis.visit_expr(er);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::AssignOp(_op, el, er) => {
|
||||
vis.visit_expr(el);
|
||||
vis.visit_expr(er);
|
||||
}
|
||||
ExprKind::Field(el, ident) => {
|
||||
vis.visit_expr(el);
|
||||
vis.visit_ident(ident);
|
||||
}
|
||||
ExprKind::Index(el, er, brackets_span) => {
|
||||
vis.visit_expr(el);
|
||||
vis.visit_expr(er);
|
||||
vis.visit_span(brackets_span);
|
||||
}
|
||||
ExprKind::Range(e1, e2, _lim) => {
|
||||
visit_opt(e1, |e1| vis.visit_expr(e1));
|
||||
visit_opt(e2, |e2| vis.visit_expr(e2));
|
||||
}
|
||||
ExprKind::Underscore => {}
|
||||
ExprKind::Path(qself, path) => {
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
ExprKind::Break(label, expr) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||
}
|
||||
ExprKind::Continue(label) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::Ret(expr) => {
|
||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||
}
|
||||
ExprKind::Yeet(expr) => {
|
||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||
}
|
||||
ExprKind::Become(expr) => vis.visit_expr(expr),
|
||||
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
|
||||
ExprKind::OffsetOf(container, fields) => {
|
||||
vis.visit_ty(container);
|
||||
for field in fields.iter_mut() {
|
||||
vis.visit_ident(field);
|
||||
}
|
||||
}
|
||||
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||
ExprKind::Struct(se) => {
|
||||
let StructExpr { qself, path, fields, rest } = se.deref_mut();
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
fields.flat_map_in_place(|field| vis.flat_map_expr_field(field));
|
||||
match rest {
|
||||
StructRest::Base(expr) => vis.visit_expr(expr),
|
||||
StructRest::Rest(_span) => {}
|
||||
StructRest::None => {}
|
||||
}
|
||||
}
|
||||
ExprKind::Paren(expr) => {
|
||||
vis.visit_expr(expr);
|
||||
}
|
||||
ExprKind::Yield(kind) => {
|
||||
let expr = kind.expr_mut();
|
||||
if let Some(expr) = expr {
|
||||
vis.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Try(expr) => vis.visit_expr(expr),
|
||||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||
ExprKind::Lit(_token) => {}
|
||||
ExprKind::IncludedBytes(_bytes) => {}
|
||||
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
|
||||
vis.visit_expr(expr);
|
||||
if let Some(ty) = ty {
|
||||
vis.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
ExprKind::Err(_guar) => {}
|
||||
ExprKind::Dummy => {}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
|
||||
vis.visit_expr(&mut e);
|
||||
Some(e)
|
||||
|
|
@ -1139,18 +583,6 @@ fn walk_flat_map_stmt_kind<T: MutVisitor>(vis: &mut T, kind: StmtKind) -> SmallV
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_vis<T: MutVisitor>(vis: &mut T, visibility: &mut Visibility) {
|
||||
let Visibility { kind, span, tokens: _ } = visibility;
|
||||
match kind {
|
||||
VisibilityKind::Public | VisibilityKind::Inherited => {}
|
||||
VisibilityKind::Restricted { path, id, shorthand: _ } => {
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
|
||||
match capture_by {
|
||||
CaptureBy::Ref => {}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -33,9 +33,7 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -57,14 +57,6 @@ impl OptimizeAttr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic, PrintAttribute)]
|
||||
pub enum DiagnosticAttribute {
|
||||
// tidy-alphabetical-start
|
||||
DoNotRecommend,
|
||||
OnUnimplemented,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic, PrintAttribute)]
|
||||
pub enum ReprAttr {
|
||||
ReprInt(IntType),
|
||||
|
|
@ -160,40 +152,52 @@ impl Deprecation {
|
|||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub enum AttributeKind {
|
||||
// tidy-alphabetical-start
|
||||
/// Represents `#[rustc_allow_const_fn_unstable]`.
|
||||
AllowConstFnUnstable(ThinVec<Symbol>),
|
||||
|
||||
/// Represents `#[allow_internal_unstable]`.
|
||||
AllowInternalUnstable(ThinVec<(Symbol, Span)>),
|
||||
|
||||
/// Represents `#[rustc_default_body_unstable]`.
|
||||
BodyStability {
|
||||
stability: DefaultBodyStability,
|
||||
/// Span of the `#[rustc_default_body_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_confusables]`.
|
||||
Confusables {
|
||||
symbols: ThinVec<Symbol>,
|
||||
// FIXME(jdonszelmann): remove when target validation code is moved
|
||||
first_span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
|
||||
ConstStability {
|
||||
stability: PartialConstStability,
|
||||
/// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_const_stable_indirect]`.
|
||||
ConstStabilityIndirect,
|
||||
Deprecation {
|
||||
deprecation: Deprecation,
|
||||
span: Span,
|
||||
},
|
||||
Diagnostic(DiagnosticAttribute),
|
||||
DocComment {
|
||||
style: AttrStyle,
|
||||
kind: CommentKind,
|
||||
span: Span,
|
||||
comment: Symbol,
|
||||
},
|
||||
|
||||
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
|
||||
Deprecation { deprecation: Deprecation, span: Span },
|
||||
|
||||
/// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
|
||||
DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
|
||||
|
||||
/// Represents `#[rustc_macro_transparency]`.
|
||||
MacroTransparency(Transparency),
|
||||
|
||||
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
|
||||
Repr(ThinVec<(ReprAttr, Span)>),
|
||||
|
||||
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
|
||||
Stability {
|
||||
stability: Stability,
|
||||
/// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute
|
||||
/// Span of the attribute.
|
||||
span: Span,
|
||||
},
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
//! - [`CombineAttributeParser`]: makes it easy to implement an attribute which should combine the
|
||||
//! contents of attributes, if an attribute appear multiple times in a list
|
||||
//!
|
||||
//! Attributes should be added to [`ATTRIBUTE_MAPPING`](crate::context::ATTRIBUTE_MAPPING) to be parsed.
|
||||
//! Attributes should be added to [`ATTRIBUTE_PARSERS`](crate::context::ATTRIBUTE_PARSERS) to be parsed.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
|
@ -51,6 +51,9 @@ type AcceptMapping<T> = &'static [(&'static [Symbol], AcceptFn<T>)];
|
|||
/// whether it has seen the attribute it has been looking for.
|
||||
///
|
||||
/// The state machine is automatically reset to parse attributes on the next item.
|
||||
///
|
||||
/// For a simpler attribute parsing interface, consider using [`SingleAttributeParser`]
|
||||
/// or [`CombineAttributeParser`] instead.
|
||||
pub(crate) trait AttributeParser: Default + 'static {
|
||||
/// The symbols for the attributes that this parser is interested in.
|
||||
///
|
||||
|
|
@ -59,6 +62,12 @@ pub(crate) trait AttributeParser: Default + 'static {
|
|||
|
||||
/// The parser has gotten a chance to accept the attributes on an item,
|
||||
/// here it can produce an attribute.
|
||||
///
|
||||
/// All finalize methods of all parsers are unconditionally called.
|
||||
/// This means you can't unconditionally return `Some` here,
|
||||
/// that'd be equivalent to unconditionally applying an attribute to
|
||||
/// every single syntax item that could have attributes applied to it.
|
||||
/// Your accept mappings should determine whether this returns something.
|
||||
fn finalize(self, cx: &FinalizeContext<'_>) -> Option<AttributeKind>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use crate::attributes::transparency::TransparencyParser;
|
|||
use crate::attributes::{AttributeParser as _, Combine, Single};
|
||||
use crate::parser::{ArgParser, MetaItemParser};
|
||||
|
||||
macro_rules! attribute_groups {
|
||||
macro_rules! attribute_parsers {
|
||||
(
|
||||
pub(crate) static $name: ident = [$($names: ty),* $(,)?];
|
||||
) => {
|
||||
|
|
@ -63,8 +63,8 @@ macro_rules! attribute_groups {
|
|||
};
|
||||
}
|
||||
|
||||
attribute_groups!(
|
||||
pub(crate) static ATTRIBUTE_MAPPING = [
|
||||
attribute_parsers!(
|
||||
pub(crate) static ATTRIBUTE_PARSERS = [
|
||||
// tidy-alphabetical-start
|
||||
BodyStabilityParser,
|
||||
ConfusablesParser,
|
||||
|
|
@ -90,7 +90,7 @@ attribute_groups!(
|
|||
///
|
||||
/// Gives [`AttributeParser`]s enough information to create errors, for example.
|
||||
pub(crate) struct AcceptContext<'a> {
|
||||
pub(crate) group_cx: &'a FinalizeContext<'a>,
|
||||
pub(crate) finalize_cx: &'a FinalizeContext<'a>,
|
||||
/// The span of the attribute currently being parsed
|
||||
pub(crate) attr_span: Span,
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ impl<'a> Deref for AcceptContext<'a> {
|
|||
type Target = FinalizeContext<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.group_cx
|
||||
&self.finalize_cx
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ impl<'sess> AttributeParser<'sess> {
|
|||
) -> Vec<Attribute> {
|
||||
let mut attributes = Vec::new();
|
||||
|
||||
let group_cx = FinalizeContext { cx: self, target_span };
|
||||
let finalize_cx = FinalizeContext { cx: self, target_span };
|
||||
|
||||
for attr in attrs {
|
||||
// If we're only looking for a single attribute, skip all the ones we don't care about.
|
||||
|
|
@ -268,9 +268,11 @@ impl<'sess> AttributeParser<'sess> {
|
|||
let args = parser.args();
|
||||
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
|
||||
|
||||
if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
|
||||
let cx =
|
||||
AcceptContext { group_cx: &group_cx, attr_span: lower_span(attr.span) };
|
||||
if let Some(accept) = ATTRIBUTE_PARSERS.0.get(parts.as_slice()) {
|
||||
let cx = AcceptContext {
|
||||
finalize_cx: &finalize_cx,
|
||||
attr_span: lower_span(attr.span),
|
||||
};
|
||||
|
||||
accept(&cx, &args)
|
||||
} else {
|
||||
|
|
@ -302,8 +304,8 @@ impl<'sess> AttributeParser<'sess> {
|
|||
}
|
||||
|
||||
let mut parsed_attributes = Vec::new();
|
||||
for f in &ATTRIBUTE_MAPPING.1 {
|
||||
if let Some(attr) = f(&group_cx) {
|
||||
for f in &ATTRIBUTE_PARSERS.1 {
|
||||
if let Some(attr) = f(&finalize_cx) {
|
||||
parsed_attributes.push(Attribute::Parsed(attr));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
|
||||
if !tcx.recursion_limit().value_within_limit(iteration) {
|
||||
// This may actually be reachable. If so, we should convert
|
||||
// this to a proper error/consider whether we should detect
|
||||
// this somewhere else.
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
|
||||
"unexpected overflowed when processing region obligations: {outlives_predicates:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(string_from_utf8_lossy_owned)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -812,11 +812,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
dest.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::pref_align_of
|
||||
| sym::needs_drop
|
||||
| sym::type_id
|
||||
| sym::type_name
|
||||
| sym::variant_count => {
|
||||
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
|
||||
intrinsic_args!(fx, args => (); intrinsic);
|
||||
|
||||
let const_val = fx
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ resolver = "2"
|
|||
|
||||
[dependencies]
|
||||
core = { path = "./sysroot_src/library/core" }
|
||||
compiler_builtins = "0.1"
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
|
|
@ -16,6 +15,7 @@ proc_macro = { path = "./sysroot_src/library/proc_macro" }
|
|||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
// add fast paths for low alignment values.
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "arm",
|
||||
target_arch = "loongarch32",
|
||||
target_arch = "m68k",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ codegen_gcc_unknown_ctarget_feature_prefix =
|
|||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = features must begin with a `+` to enable or `-` to disable it
|
||||
|
||||
codegen_gcc_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_gcc_forbidden_ctarget_feature =
|
||||
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use rustc_span::def_id::DefId;
|
|||
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::errors::InvalidMinimumAlignment;
|
||||
use crate::type_of::LayoutGccExt;
|
||||
|
||||
fn set_global_alignment<'gcc, 'tcx>(
|
||||
|
|
@ -29,13 +28,8 @@ fn set_global_alignment<'gcc, 'tcx>(
|
|||
// The target may require greater alignment for globals than the type does.
|
||||
// Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
|
||||
// which can force it to be smaller. Rust doesn't support this yet.
|
||||
if let Some(min) = cx.sess().target.min_global_align {
|
||||
match Align::from_bits(min) {
|
||||
Ok(min) => align = align.max(min),
|
||||
Err(err) => {
|
||||
cx.sess().dcx().emit_err(InvalidMinimumAlignment { err: err.to_string() });
|
||||
}
|
||||
}
|
||||
if let Some(min_global) = cx.sess().target.min_global_align {
|
||||
align = Ord::max(align, min_global);
|
||||
}
|
||||
gv.set_alignment(align.bytes() as i32);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,12 +47,6 @@ pub(crate) struct UnwindingInlineAsm {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_invalid_minimum_alignment)]
|
||||
pub(crate) struct InvalidMinimumAlignment {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_copy_bitcode)]
|
||||
pub(crate) struct CopyBitcode {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(rustc_private, decl_macro, never_type, trusted_len)]
|
||||
#![feature(rustc_private)]
|
||||
#![allow(broken_intra_doc_links)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ gimli = "0.31"
|
|||
itertools = "0.12"
|
||||
libc = "0.2"
|
||||
measureme = "12.0.1"
|
||||
object = { version = "0.36.3", default-features = false, features = ["std", "read"] }
|
||||
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
|
||||
rustc-demangle = "0.1.21"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
|
|
|
|||
|
|
@ -19,12 +19,6 @@ codegen_llvm_from_llvm_diag = {$message}
|
|||
|
||||
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
|
||||
|
||||
codegen_llvm_invalid_minimum_alignment_not_power_of_two =
|
||||
invalid minimum global alignment: {$align} is not power of 2
|
||||
|
||||
codegen_llvm_invalid_minimum_alignment_too_large =
|
||||
invalid minimum global alignment: {$align} is too large
|
||||
|
||||
codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
|
||||
codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
|
||||
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
InlineAsmArch::Nvptx64 => {}
|
||||
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
|
||||
InlineAsmArch::Hexagon => {}
|
||||
InlineAsmArch::LoongArch64 => {
|
||||
InlineAsmArch::LoongArch32 | InlineAsmArch::LoongArch64 => {
|
||||
constraints.extend_from_slice(&[
|
||||
"~{$fcc0}".to_string(),
|
||||
"~{$fcc1}".to_string(),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
@ -256,11 +257,11 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
|
|||
StackProbeType::Inline => "inline-asm",
|
||||
// Flag our internal `__rust_probestack` function as the stack probe symbol.
|
||||
// This is defined in the `compiler-builtins` crate for each architecture.
|
||||
StackProbeType::Call => "__rust_probestack",
|
||||
StackProbeType::Call => &mangle_internal_symbol(cx.tcx, "__rust_probestack"),
|
||||
// Pick from the two above based on the LLVM version.
|
||||
StackProbeType::InlineOrCall { min_llvm_version_for_inline } => {
|
||||
if llvm_util::get_version() < min_llvm_version_for_inline {
|
||||
"__rust_probestack"
|
||||
&mangle_internal_symbol(cx.tcx, "__rust_probestack")
|
||||
} else {
|
||||
"inline-asm"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use rustc_abi::{
|
||||
Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
|
||||
};
|
||||
use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_hir::LangItem;
|
||||
|
|
@ -20,9 +18,7 @@ use rustc_middle::{bug, span_bug};
|
|||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::common::{AsCCharPtr, CodegenCx};
|
||||
use crate::errors::{
|
||||
InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
|
||||
};
|
||||
use crate::errors::SymbolAlreadyDefined;
|
||||
use crate::llvm::{self, True};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
|
|
@ -149,22 +145,10 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
|
|||
// The target may require greater alignment for globals than the type does.
|
||||
// Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
|
||||
// which can force it to be smaller. Rust doesn't support this yet.
|
||||
if let Some(min) = cx.sess().target.min_global_align {
|
||||
match Align::from_bits(min) {
|
||||
Ok(min) => align = align.max(min),
|
||||
Err(err) => match err {
|
||||
AlignFromBytesError::NotPowerOfTwo(align) => {
|
||||
cx.sess().dcx().emit_err(InvalidMinimumAlignmentNotPowerOfTwo { align });
|
||||
}
|
||||
AlignFromBytesError::TooLarge(align) => {
|
||||
cx.sess().dcx().emit_err(InvalidMinimumAlignmentTooLarge { align });
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
llvm::LLVMSetAlignment(gv, align.bytes() as u32);
|
||||
if let Some(min_global) = cx.sess().target.min_global_align {
|
||||
align = Ord::max(align, min_global);
|
||||
}
|
||||
llvm::set_alignment(gv, align);
|
||||
}
|
||||
|
||||
fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
|
|
|
|||
|
|
@ -57,18 +57,6 @@ pub(crate) struct SymbolAlreadyDefined<'a> {
|
|||
pub symbol_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_invalid_minimum_alignment_not_power_of_two)]
|
||||
pub(crate) struct InvalidMinimumAlignmentNotPowerOfTwo {
|
||||
pub align: u64,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_invalid_minimum_alignment_too_large)]
|
||||
pub(crate) struct InvalidMinimumAlignmentTooLarge {
|
||||
pub align: u64,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ libc = "0.2.50"
|
|||
# tidy-alphabetical-end
|
||||
|
||||
[dependencies.object]
|
||||
version = "0.36.2"
|
||||
version = "0.37.0"
|
||||
default-features = false
|
||||
features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"]
|
||||
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
|
|||
(Architecture::X86_64, None) => elf::EM_X86_64,
|
||||
(Architecture::X86_64_X32, None) => elf::EM_X86_64,
|
||||
(Architecture::Hexagon, None) => elf::EM_HEXAGON,
|
||||
(Architecture::LoongArch32, None) => elf::EM_LOONGARCH,
|
||||
(Architecture::LoongArch64, None) => elf::EM_LOONGARCH,
|
||||
(Architecture::M68k, None) => elf::EM_68K,
|
||||
(Architecture::Mips, None) => elf::EM_MIPS,
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
|
|||
|
||||
e_flags
|
||||
}
|
||||
Architecture::LoongArch64 => {
|
||||
Architecture::LoongArch32 | Architecture::LoongArch64 => {
|
||||
// Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
|
||||
let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
|
||||
|
||||
|
|
|
|||
|
|
@ -150,11 +150,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
value
|
||||
}
|
||||
sym::pref_align_of
|
||||
| sym::needs_drop
|
||||
| sym::type_id
|
||||
| sym::type_name
|
||||
| sym::variant_count => {
|
||||
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
|
||||
let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
|
||||
OperandRef::from_const(bx, value, result.layout.ty).immediate_or_packed_pair(bx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
{
|
||||
let from_backend_ty = bx.backend_type(operand.layout);
|
||||
let to_backend_ty = bx.backend_type(cast);
|
||||
Some(OperandValue::Immediate(self.transmute_immediate(
|
||||
Some(OperandValue::Immediate(transmute_immediate(
|
||||
bx,
|
||||
imm,
|
||||
from_scalar,
|
||||
|
|
@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);
|
||||
let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);
|
||||
Some(OperandValue::Pair(
|
||||
self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
|
||||
self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
|
||||
transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
|
||||
transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// valid ranges. For example, `char`s are passed as just `i32`, with no
|
||||
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
|
||||
// the range of the input value too, not just the output range.
|
||||
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
|
||||
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
|
||||
(Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),
|
||||
|
|
@ -365,98 +365,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
Some(imm)
|
||||
}
|
||||
|
||||
/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
|
||||
/// or an [`OperandValue::Pair`] to an immediate of the target type.
|
||||
///
|
||||
/// `to_backend_ty` must be the *non*-immediate backend type (so it will be
|
||||
/// `i8`, not `i1`, for `bool`-like types.)
|
||||
fn transmute_immediate(
|
||||
&self,
|
||||
bx: &mut Bx,
|
||||
mut imm: Bx::Value,
|
||||
from_scalar: abi::Scalar,
|
||||
from_backend_ty: Bx::Type,
|
||||
to_scalar: abi::Scalar,
|
||||
to_backend_ty: Bx::Type,
|
||||
) -> Bx::Value {
|
||||
assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
|
||||
|
||||
// While optimizations will remove no-op transmutes, they might still be
|
||||
// there in debug or things that aren't no-op in MIR because they change
|
||||
// the Rust type but not the underlying layout/niche.
|
||||
if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
|
||||
return imm;
|
||||
}
|
||||
|
||||
use abi::Primitive::*;
|
||||
imm = bx.from_immediate(imm);
|
||||
|
||||
// If we have a scalar, we must already know its range. Either
|
||||
//
|
||||
// 1) It's a parameter with `range` parameter metadata,
|
||||
// 2) It's something we `load`ed with `!range` metadata, or
|
||||
// 3) After a transmute we `assume`d the range (see below).
|
||||
//
|
||||
// That said, last time we tried removing this, it didn't actually help
|
||||
// the rustc-perf results, so might as well keep doing it
|
||||
// <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
|
||||
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
|
||||
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
|
||||
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
|
||||
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
|
||||
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
|
||||
(Pointer(..), Int(..)) => {
|
||||
// FIXME: this exposes the provenance, which shouldn't be necessary.
|
||||
bx.ptrtoint(imm, to_backend_ty)
|
||||
}
|
||||
(Float(_), Pointer(..)) => {
|
||||
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
||||
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
|
||||
}
|
||||
(Pointer(..), Float(_)) => {
|
||||
// FIXME: this exposes the provenance, which shouldn't be necessary.
|
||||
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
|
||||
bx.bitcast(int_imm, to_backend_ty)
|
||||
}
|
||||
};
|
||||
|
||||
// This `assume` remains important for cases like (a conceptual)
|
||||
// transmute::<u32, NonZeroU32>(x) == 0
|
||||
// since it's never passed to something with parameter metadata (especially
|
||||
// after MIR inlining) so the only way to tell the backend about the
|
||||
// constraint that the `transmute` introduced is to `assume` it.
|
||||
self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty);
|
||||
|
||||
imm = bx.to_immediate_scalar(imm, to_scalar);
|
||||
imm
|
||||
}
|
||||
|
||||
fn assume_scalar_range(
|
||||
&self,
|
||||
bx: &mut Bx,
|
||||
imm: Bx::Value,
|
||||
scalar: abi::Scalar,
|
||||
backend_ty: Bx::Type,
|
||||
) {
|
||||
if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
match scalar.primitive() {
|
||||
abi::Primitive::Int(..) => {
|
||||
let range = scalar.valid_range(self.cx);
|
||||
bx.assume_integer_range(imm, backend_ty, range);
|
||||
}
|
||||
abi::Primitive::Pointer(abi::AddressSpace::DATA)
|
||||
if !scalar.valid_range(self.cx).contains(0) =>
|
||||
{
|
||||
bx.assume_nonnull(imm);
|
||||
}
|
||||
abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_rvalue_unsized(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
|
@ -1231,3 +1139,93 @@ impl OperandValueKind {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
|
||||
/// or an [`OperandValue::Pair`] to an immediate of the target type.
|
||||
///
|
||||
/// `to_backend_ty` must be the *non*-immediate backend type (so it will be
|
||||
/// `i8`, not `i1`, for `bool`-like types.)
|
||||
fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
mut imm: Bx::Value,
|
||||
from_scalar: abi::Scalar,
|
||||
from_backend_ty: Bx::Type,
|
||||
to_scalar: abi::Scalar,
|
||||
to_backend_ty: Bx::Type,
|
||||
) -> Bx::Value {
|
||||
assert_eq!(from_scalar.size(bx.cx()), to_scalar.size(bx.cx()));
|
||||
|
||||
// While optimizations will remove no-op transmutes, they might still be
|
||||
// there in debug or things that aren't no-op in MIR because they change
|
||||
// the Rust type but not the underlying layout/niche.
|
||||
if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
|
||||
return imm;
|
||||
}
|
||||
|
||||
use abi::Primitive::*;
|
||||
imm = bx.from_immediate(imm);
|
||||
|
||||
// If we have a scalar, we must already know its range. Either
|
||||
//
|
||||
// 1) It's a parameter with `range` parameter metadata,
|
||||
// 2) It's something we `load`ed with `!range` metadata, or
|
||||
// 3) After a transmute we `assume`d the range (see below).
|
||||
//
|
||||
// That said, last time we tried removing this, it didn't actually help
|
||||
// the rustc-perf results, so might as well keep doing it
|
||||
// <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
|
||||
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
|
||||
|
||||
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
|
||||
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
|
||||
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
|
||||
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
|
||||
(Pointer(..), Int(..)) => {
|
||||
// FIXME: this exposes the provenance, which shouldn't be necessary.
|
||||
bx.ptrtoint(imm, to_backend_ty)
|
||||
}
|
||||
(Float(_), Pointer(..)) => {
|
||||
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
||||
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
|
||||
}
|
||||
(Pointer(..), Float(_)) => {
|
||||
// FIXME: this exposes the provenance, which shouldn't be necessary.
|
||||
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
|
||||
bx.bitcast(int_imm, to_backend_ty)
|
||||
}
|
||||
};
|
||||
|
||||
// This `assume` remains important for cases like (a conceptual)
|
||||
// transmute::<u32, NonZeroU32>(x) == 0
|
||||
// since it's never passed to something with parameter metadata (especially
|
||||
// after MIR inlining) so the only way to tell the backend about the
|
||||
// constraint that the `transmute` introduced is to `assume` it.
|
||||
assume_scalar_range(bx, imm, to_scalar, to_backend_ty);
|
||||
|
||||
imm = bx.to_immediate_scalar(imm, to_scalar);
|
||||
imm
|
||||
}
|
||||
|
||||
fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
imm: Bx::Value,
|
||||
scalar: abi::Scalar,
|
||||
backend_ty: Bx::Type,
|
||||
) {
|
||||
if matches!(bx.cx().sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(bx.cx()) {
|
||||
return;
|
||||
}
|
||||
|
||||
match scalar.primitive() {
|
||||
abi::Primitive::Int(..) => {
|
||||
let range = scalar.valid_range(bx.cx());
|
||||
bx.assume_integer_range(imm, backend_ty, range);
|
||||
}
|
||||
abi::Primitive::Pointer(abi::AddressSpace::DATA)
|
||||
if !scalar.valid_range(bx.cx()).contains(0) =>
|
||||
{
|
||||
bx.assume_nonnull(imm);
|
||||
}
|
||||
abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,10 +356,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
hir::ConstContext::ConstFn => true,
|
||||
_ => {
|
||||
// For indirect places, we are not creating a new permanent borrow, it's just as
|
||||
// transient as the already existing one. For reborrowing references this is handled
|
||||
// at the top of `visit_rvalue`, but for raw pointers we handle it here.
|
||||
// Pointers/references to `static mut` and cases where the `*` is not the first
|
||||
// projection also end up here.
|
||||
// transient as the already existing one.
|
||||
// Locals with StorageDead do not live beyond the evaluation and can
|
||||
// thus safely be borrowed without being able to be leaked to the final
|
||||
// value of the constant.
|
||||
|
|
@ -395,7 +392,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
}
|
||||
|
||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let body_id = self.body.source.def_id().expect_local();
|
||||
let host_polarity = match self.const_kind() {
|
||||
|
|
|
|||
|
|
@ -227,12 +227,11 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
|||
|
||||
// Keep interning as long as there are things to intern.
|
||||
// We show errors if there are dangling pointers, or mutable pointers in immutable contexts
|
||||
// (i.e., everything except for `static mut`). When these errors affect references, it is
|
||||
// unfortunate that we show these errors here and not during validation, since validation can
|
||||
// show much nicer errors. However, we do need these checks to be run on all pointers, including
|
||||
// raw pointers, so we cannot rely on validation to catch them -- and since interning runs
|
||||
// before validation, and interning doesn't know the type of anything, this means we can't show
|
||||
// better errors. Maybe we should consider doing validation before interning in the future.
|
||||
// (i.e., everything except for `static mut`). We only return these errors as a `Result`
|
||||
// so that the caller can run validation, and subsequently only report interning errors
|
||||
// if validation fails. Validation has the better error messages so we prefer those, but
|
||||
// interning has better coverage since it "sees" *all* pointers, including raw pointers and
|
||||
// references stored in unions.
|
||||
while let Some(prov) = todo.pop() {
|
||||
trace!(?prov);
|
||||
let alloc_id = prov.alloc_id();
|
||||
|
|
@ -279,12 +278,12 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
|||
// when there is memory there that someone might expect to be mutable, but we make it immutable.
|
||||
let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id);
|
||||
if !dangling {
|
||||
// Found a mutable reference inside a const where inner allocations should be
|
||||
// Found a mutable pointer inside a const where inner allocations should be
|
||||
// immutable.
|
||||
if !ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
|
||||
span_bug!(
|
||||
ecx.tcx.span,
|
||||
"the static const safety checks accepted mutable references they should not have accepted"
|
||||
"the static const safety checks accepted a mutable pointer they should not have accepted"
|
||||
);
|
||||
}
|
||||
// Prefer dangling pointer errors over mutable pointer errors
|
||||
|
|
|
|||
|
|
@ -50,13 +50,6 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
|||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env))
|
||||
}
|
||||
sym::pref_align_of => {
|
||||
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
|
||||
let layout = tcx
|
||||
.layout_of(typing_env.as_query_input(tp_ty))
|
||||
.map_err(|e| err_inval!(Layout(*e)))?;
|
||||
ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
|
||||
}
|
||||
sym::type_id => {
|
||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128())
|
||||
|
|
@ -144,14 +137,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
self.write_scalar(Scalar::from_target_usize(result, self), dest)?;
|
||||
}
|
||||
|
||||
sym::pref_align_of
|
||||
| sym::needs_drop
|
||||
| sym::type_id
|
||||
| sym::type_name
|
||||
| sym::variant_count => {
|
||||
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
|
||||
let gid = GlobalId { instance, promoted: None };
|
||||
let ty = match intrinsic_name {
|
||||
sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
|
||||
sym::variant_count => self.tcx.types.usize,
|
||||
sym::needs_drop => self.tcx.types.bool,
|
||||
sym::type_id => self.tcx.types.u128,
|
||||
sym::type_name => Ty::new_static_str(self.tcx.tcx),
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ pub enum MaybeEnteredSpan {
|
|||
macro_rules! enter_trace_span {
|
||||
($machine:ident, $($tt:tt)*) => {
|
||||
if $machine::TRACING_ENABLED {
|
||||
$crate::interpret::tracing_utils::MaybeEnteredSpan::Some(tracing::info_span!($($tt)*).entered())
|
||||
$crate::interpret::util::MaybeEnteredSpan::Some(tracing::info_span!($($tt)*).entered())
|
||||
} else {
|
||||
$crate::interpret::tracing_utils::MaybeEnteredSpan::None
|
||||
$crate::interpret::util::MaybeEnteredSpan::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#![feature(dropck_eyepatch)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
|||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
unic-langid = { version = "0.9.0", features = ["macros"] }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use intl_memoizer::concurrent::IntlLangMemoizer;
|
|||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
use tracing::{instrument, trace};
|
||||
pub use unic_langid::{LanguageIdentifier, langid};
|
||||
|
||||
|
|
@ -106,8 +107,7 @@ impl From<Vec<FluentError>> for TranslationBundleError {
|
|||
/// (overriding any conflicting messages).
|
||||
#[instrument(level = "trace")]
|
||||
pub fn fluent_bundle(
|
||||
sysroot: PathBuf,
|
||||
sysroot_candidates: Vec<PathBuf>,
|
||||
sysroot_candidates: SmallVec<[PathBuf; 2]>,
|
||||
requested_locale: Option<LanguageIdentifier>,
|
||||
additional_ftl_path: Option<&Path>,
|
||||
with_directionality_markers: bool,
|
||||
|
|
@ -141,7 +141,7 @@ pub fn fluent_bundle(
|
|||
// If the user requests the default locale then don't try to load anything.
|
||||
if let Some(requested_locale) = requested_locale {
|
||||
let mut found_resources = false;
|
||||
for mut sysroot in Some(sysroot).into_iter().chain(sysroot_candidates.into_iter()) {
|
||||
for mut sysroot in sysroot_candidates {
|
||||
sysroot.push("share");
|
||||
sysroot.push("locale");
|
||||
sysroot.push(requested_locale.to_string());
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(error_reporter)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(yeet_expr)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ expand_feature_not_allowed =
|
|||
expand_feature_removed =
|
||||
feature has been removed
|
||||
.label = feature has been removed
|
||||
.note = removed in {$removed_rustc_version} (you are using {$current_rustc_version}){$pull_note}
|
||||
.reason = {$reason}
|
||||
|
||||
expand_glob_delegation_outside_impls =
|
||||
|
|
|
|||
|
|
@ -80,9 +80,20 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
|
|||
|
||||
// If the enabled feature has been removed, issue an error.
|
||||
if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name == f.feature.name) {
|
||||
let pull_note = if let Some(pull) = f.pull {
|
||||
format!(
|
||||
"; see <https://github.com/rust-lang/rust/pull/{}> for more information",
|
||||
pull
|
||||
)
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
sess.dcx().emit_err(FeatureRemoved {
|
||||
span: mi.span(),
|
||||
reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
|
||||
removed_rustc_version: f.feature.since,
|
||||
current_rustc_version: sess.cfg_version,
|
||||
pull_note,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,12 +154,16 @@ pub(crate) struct HelperAttributeNameInvalid {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_feature_removed, code = E0557)]
|
||||
#[note]
|
||||
pub(crate) struct FeatureRemoved<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub reason: Option<FeatureRemovedReason<'a>>,
|
||||
pub removed_rustc_version: &'a str,
|
||||
pub current_rustc_version: &'a str,
|
||||
pub pull_note: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -259,6 +259,8 @@ declare_features! (
|
|||
/// Allows some increased flexibility in the name resolution rules,
|
||||
/// especially around globs and shadowing (RFC 1560).
|
||||
(accepted, item_like_imports, "1.15.0", Some(35120)),
|
||||
// Allows using the `kl` and `widekl` target features and the associated intrinsics
|
||||
(accepted, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
|
||||
/// Allows `'a: { break 'a; }`.
|
||||
(accepted, label_break_value, "1.65.0", Some(48594)),
|
||||
/// Allows `let...else` statements.
|
||||
|
|
@ -382,6 +384,8 @@ declare_features! (
|
|||
(accepted, self_in_typedefs, "1.32.0", Some(49303)),
|
||||
/// Allows `Self` struct constructor (RFC 2302).
|
||||
(accepted, self_struct_ctor, "1.32.0", Some(51994)),
|
||||
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
|
||||
(accepted, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
|
||||
/// Shortern the tail expression lifetime
|
||||
(accepted, shorter_tail_lifetimes, "1.84.0", Some(123739)),
|
||||
/// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//! List of the removed feature gates.
|
||||
|
||||
use std::num::{NonZero, NonZeroU32};
|
||||
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::{Feature, to_nonzero};
|
||||
|
|
@ -7,11 +9,21 @@ use super::{Feature, to_nonzero};
|
|||
pub struct RemovedFeature {
|
||||
pub feature: Feature,
|
||||
pub reason: Option<&'static str>,
|
||||
pub pull: Option<NonZero<u32>>,
|
||||
}
|
||||
|
||||
macro_rules! opt_nonzero_u32 {
|
||||
() => {
|
||||
None
|
||||
};
|
||||
($val:expr) => {
|
||||
Some(NonZeroU32::new($val).unwrap())
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! declare_features {
|
||||
($(
|
||||
$(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr),
|
||||
$(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr $(, $pull:expr)?),
|
||||
)+) => {
|
||||
/// Formerly unstable features that have now been removed.
|
||||
pub static REMOVED_LANG_FEATURES: &[RemovedFeature] = &[
|
||||
|
|
@ -21,7 +33,8 @@ macro_rules! declare_features {
|
|||
since: $ver,
|
||||
issue: to_nonzero($issue),
|
||||
},
|
||||
reason: $reason
|
||||
reason: $reason,
|
||||
pull: opt_nonzero_u32!($($pull)?),
|
||||
}),+
|
||||
];
|
||||
};
|
||||
|
|
@ -40,64 +53,64 @@ declare_features! (
|
|||
// version they got originally added in.)
|
||||
|
||||
/// Allows using the `amdgpu-kernel` ABI.
|
||||
(removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None),
|
||||
(removed, advanced_slice_patterns, "1.0.0", Some(62254),
|
||||
Some("merged into `#![feature(slice_patterns)]`")),
|
||||
(removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495),
|
||||
(removed, advanced_slice_patterns, "1.42.0", Some(62254),
|
||||
Some("merged into `#![feature(slice_patterns)]`"), 67712),
|
||||
(removed, allocator, "1.0.0", None, None),
|
||||
/// Allows a test to fail without failing the whole suite.
|
||||
(removed, allow_fail, "1.19.0", Some(46488), Some("removed due to no clear use cases")),
|
||||
(removed, allow_fail, "1.60.0", Some(46488), Some("removed due to no clear use cases"), 93416),
|
||||
(removed, await_macro, "1.38.0", Some(50547),
|
||||
Some("subsumed by `.await` syntax")),
|
||||
Some("subsumed by `.await` syntax"), 62293),
|
||||
/// Allows using the `box $expr` syntax.
|
||||
(removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`")),
|
||||
(removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`"), 108471),
|
||||
/// Allows capturing disjoint fields in a closure/coroutine (RFC 2229).
|
||||
(removed, capture_disjoint_fields, "1.49.0", Some(53488), Some("stabilized in Rust 2021")),
|
||||
(removed, capture_disjoint_fields, "1.69.0", Some(53488), Some("stabilized in Rust 2021"), 108550),
|
||||
/// Allows comparing raw pointers during const eval.
|
||||
(removed, const_compare_raw_pointers, "1.46.0", Some(53020),
|
||||
Some("cannot be allowed in const eval in any meaningful way")),
|
||||
Some("cannot be allowed in const eval in any meaningful way"), 73398),
|
||||
/// Allows limiting the evaluation steps of const expressions
|
||||
(removed, const_eval_limit, "1.43.0", Some(67217), Some("removed the limit entirely")),
|
||||
(removed, const_eval_limit, "1.72.0", Some(67217), Some("removed the limit entirely"), 103877),
|
||||
/// Allows non-trivial generic constants which have to be manually propagated upwards.
|
||||
(removed, const_evaluatable_checked, "1.48.0", Some(76560), Some("renamed to `generic_const_exprs`")),
|
||||
(removed, const_evaluatable_checked, "1.56.0", Some(76560), Some("renamed to `generic_const_exprs`"), 88369),
|
||||
/// Allows the definition of `const` functions with some advanced features.
|
||||
(removed, const_fn, "1.54.0", Some(57563),
|
||||
Some("split into finer-grained feature gates")),
|
||||
Some("split into finer-grained feature gates"), 85109),
|
||||
/// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
|
||||
(removed, const_generics, "1.34.0", Some(44580),
|
||||
Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")),
|
||||
(removed, const_generics, "1.56.0", Some(44580),
|
||||
Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`"), 88369),
|
||||
/// Allows `[x; N]` where `x` is a constant (RFC 2203).
|
||||
(removed, const_in_array_repeat_expressions, "1.37.0", Some(49147),
|
||||
Some("removed due to causing promotable bugs")),
|
||||
(removed, const_in_array_repeat_expressions, "1.51.0", Some(49147),
|
||||
Some("removed due to causing promotable bugs"), 80404),
|
||||
/// Allows casting raw pointers to `usize` during const eval.
|
||||
(removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910),
|
||||
Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
|
||||
Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported"), 87020),
|
||||
/// Allows `T: ?const Trait` syntax in bounds.
|
||||
(removed, const_trait_bound_opt_out, "1.42.0", Some(67794),
|
||||
Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")),
|
||||
(removed, const_trait_bound_opt_out, "1.56.0", Some(67794),
|
||||
Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]"), 88328),
|
||||
/// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
|
||||
(removed, crate_visibility_modifier, "1.63.0", Some(53120), Some("removed in favor of `pub(crate)`")),
|
||||
(removed, crate_visibility_modifier, "1.63.0", Some(53120), Some("removed in favor of `pub(crate)`"), 97254),
|
||||
/// Allows using custom attributes (RFC 572).
|
||||
(removed, custom_attribute, "1.0.0", Some(29642),
|
||||
Some("removed in favor of `#![register_tool]` and `#![register_attr]`")),
|
||||
Some("removed in favor of `#![register_tool]` and `#![register_attr]`"), 66070),
|
||||
/// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
|
||||
(removed, custom_derive, "1.32.0", Some(29644),
|
||||
Some("subsumed by `#[proc_macro_derive]`")),
|
||||
/// Allows default type parameters to influence type inference.
|
||||
(removed, default_type_parameter_fallback, "1.82.0", Some(27336),
|
||||
Some("never properly implemented; requires significant design work")),
|
||||
Some("never properly implemented; requires significant design work"), 127655),
|
||||
/// Allows deriving traits as per `SmartPointer` specification
|
||||
(removed, derive_smart_pointer, "1.79.0", Some(123430), Some("replaced by `CoercePointee`")),
|
||||
(removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284),
|
||||
/// Allows using `#[doc(keyword = "...")]`.
|
||||
(removed, doc_keyword, "1.28.0", Some(51315),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`")),
|
||||
(removed, doc_keyword, "1.58.0", Some(51315),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`"), 90420),
|
||||
/// Allows using `doc(primitive)` without a future-incompat warning.
|
||||
(removed, doc_primitive, "1.56.0", Some(88070),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`")),
|
||||
(removed, doc_primitive, "1.58.0", Some(88070),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`"), 90420),
|
||||
/// Allows `#[doc(spotlight)]`.
|
||||
/// The attribute was renamed to `#[doc(notable_trait)]`
|
||||
/// and the feature to `doc_notable_trait`.
|
||||
(removed, doc_spotlight, "1.22.0", Some(45040),
|
||||
Some("renamed to `doc_notable_trait`")),
|
||||
(removed, doc_spotlight, "1.53.0", Some(45040),
|
||||
Some("renamed to `doc_notable_trait`"), 80965),
|
||||
/// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
|
||||
(removed, dropck_parametricity, "1.38.0", Some(28498), None),
|
||||
/// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible[^1].
|
||||
|
|
@ -107,159 +120,162 @@ declare_features! (
|
|||
/// Renamed from `object_safe_for_dispatch`.
|
||||
///
|
||||
/// [^1]: Formerly known as "object safe".
|
||||
(removed, dyn_compatible_for_dispatch, "1.83.0", Some(43561),
|
||||
Some("removed, not used heavily and represented additional complexity in dyn compatibility")),
|
||||
(removed, dyn_compatible_for_dispatch, "1.87.0", Some(43561),
|
||||
Some("removed, not used heavily and represented additional complexity in dyn compatibility"), 136522),
|
||||
/// Uses generic effect parameters for ~const bounds
|
||||
(removed, effects, "1.84.0", Some(102090),
|
||||
Some("removed, redundant with `#![feature(const_trait_impl)]`")),
|
||||
Some("removed, redundant with `#![feature(const_trait_impl)]`"), 132479),
|
||||
/// Allows defining `existential type`s.
|
||||
(removed, existential_type, "1.38.0", Some(63063),
|
||||
Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
|
||||
/// Paths of the form: `extern::foo::bar`
|
||||
(removed, extern_in_paths, "1.33.0", Some(55600),
|
||||
Some("subsumed by `::foo::bar` paths")),
|
||||
Some("subsumed by `::foo::bar` paths"), 57572),
|
||||
/// Allows `#[doc(include = "some-file")]`.
|
||||
(removed, external_doc, "1.54.0", Some(44732),
|
||||
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
|
||||
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations"), 85457),
|
||||
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
||||
(removed, ffi_returns_twice, "1.78.0", Some(58314),
|
||||
Some("being investigated by the ffi-unwind project group")),
|
||||
Some("being investigated by the ffi-unwind project group"), 120502),
|
||||
/// Allows generators to be cloned.
|
||||
(removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
|
||||
(removed, generator_clone, "1.75.0", Some(95360), Some("renamed to `coroutine_clone`"), 116958),
|
||||
/// Allows defining generators.
|
||||
(removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")),
|
||||
(removed, generators, "1.75.0", Some(43122), Some("renamed to `coroutines`"), 116958),
|
||||
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
|
||||
(removed, generic_associated_types_extended, "1.85.0", Some(95451),
|
||||
Some(
|
||||
"feature needs overhaul and reimplementation pending \
|
||||
better implied higher-ranked implied bounds support"
|
||||
)
|
||||
),
|
||||
133768
|
||||
),
|
||||
(removed, import_shadowing, "1.0.0", None, None),
|
||||
/// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
|
||||
(removed, in_band_lifetimes, "1.23.0", Some(44524),
|
||||
Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
|
||||
(removed, in_band_lifetimes, "1.61.0", Some(44524),
|
||||
Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity"), 93845),
|
||||
/// Allows inferring `'static` outlives requirements (RFC 2093).
|
||||
(removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
|
||||
Some("removed as it caused some confusion and discussion was inactive for years")),
|
||||
Some("removed as it caused some confusion and discussion was inactive for years"), 97875),
|
||||
/// Allow anonymous constants from an inline `const` block in pattern position
|
||||
(removed, inline_const_pat, "1.88.0", Some(76001),
|
||||
Some("removed due to implementation concerns as it requires significant refactorings")),
|
||||
Some("removed due to implementation concerns as it requires significant refactorings"), 138492),
|
||||
/// Lazily evaluate constants. This allows constants to depend on type parameters.
|
||||
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
|
||||
(removed, lazy_normalization_consts, "1.56.0", Some(72219), Some("superseded by `generic_const_exprs`"), 88369),
|
||||
/// Changes `impl Trait` to capture all lifetimes in scope.
|
||||
(removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
|
||||
(removed, lifetime_capture_rules_2024, "1.87.0", None, Some("unnecessary -- use edition 2024 instead"), 136787),
|
||||
/// Allows using the `#[link_args]` attribute.
|
||||
(removed, link_args, "1.53.0", Some(29596),
|
||||
Some("removed in favor of using `-C link-arg=ARG` on command line, \
|
||||
which is available from cargo build scripts with `cargo:rustc-link-arg` now")),
|
||||
which is available from cargo build scripts with `cargo:rustc-link-arg` now"), 83820),
|
||||
(removed, macro_reexport, "1.0.0", Some(29638),
|
||||
Some("subsumed by `pub use`")),
|
||||
Some("subsumed by `pub use`"), 49982),
|
||||
/// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls.
|
||||
(removed, main, "1.53.0", Some(29634), None),
|
||||
(removed, main, "1.53.0", Some(29634), None, 84217),
|
||||
(removed, managed_boxes, "1.0.0", None, None),
|
||||
/// Allows the use of type alias impl trait in function return positions
|
||||
(removed, min_type_alias_impl_trait, "1.56.0", Some(63063),
|
||||
Some("removed in favor of full type_alias_impl_trait")),
|
||||
Some("removed in favor of full type_alias_impl_trait"), 87564),
|
||||
/// Make `mut` not reset the binding mode on edition >= 2024.
|
||||
(removed, mut_preserve_binding_mode_2024, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`")),
|
||||
(removed, mut_preserve_binding_mode_2024, "1.80.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`"), 125168),
|
||||
(removed, needs_allocator, "1.4.0", Some(27389),
|
||||
Some("subsumed by `#![feature(allocator_internals)]`")),
|
||||
/// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
|
||||
(removed, negate_unsigned, "1.0.0", Some(29645), None),
|
||||
/// Allows `#[no_coverage]` on functions.
|
||||
/// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]`
|
||||
(removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`")),
|
||||
(removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656),
|
||||
/// Allows `#[no_debug]`.
|
||||
(removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand")),
|
||||
(removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667),
|
||||
/// Note: this feature was previously recorded in a separate
|
||||
/// `STABLE_REMOVED` list because it, uniquely, was once stable but was
|
||||
/// then removed. But there was no utility storing it separately, so now
|
||||
/// it's in this list.
|
||||
(removed, no_stack_check, "1.0.0", None, None),
|
||||
(removed, no_stack_check, "1.0.0", None, None, 40110),
|
||||
/// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible (object safe).
|
||||
/// Renamed to `dyn_compatible_for_dispatch`.
|
||||
(removed, object_safe_for_dispatch, "1.83.0", Some(43561),
|
||||
Some("renamed to `dyn_compatible_for_dispatch`")),
|
||||
Some("renamed to `dyn_compatible_for_dispatch`"), 131511),
|
||||
/// Allows using `#[on_unimplemented(..)]` on traits.
|
||||
/// (Moved to `rustc_attrs`.)
|
||||
(removed, on_unimplemented, "1.40.0", None, None),
|
||||
(removed, on_unimplemented, "1.40.0", None, None, 65794),
|
||||
/// A way to temporarily opt out of opt-in copy. This will *never* be accepted.
|
||||
(removed, opt_out_copy, "1.0.0", None, None),
|
||||
(removed, opt_out_copy, "1.0.0", None, None, 20740),
|
||||
/// Allows features specific to OIBIT (now called auto traits).
|
||||
/// Renamed to `auto_traits`.
|
||||
(removed, optin_builtin_traits, "1.0.0", Some(13231),
|
||||
Some("renamed to `auto_traits`")),
|
||||
(removed, optin_builtin_traits, "1.50.0", Some(13231),
|
||||
Some("renamed to `auto_traits`"), 79336),
|
||||
/// Allows overlapping impls of marker traits.
|
||||
(removed, overlapping_marker_traits, "1.42.0", Some(29864),
|
||||
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
|
||||
Some("removed in favor of `#![feature(marker_trait_attr)]`"), 68544),
|
||||
(removed, panic_implementation, "1.28.0", Some(44489),
|
||||
Some("subsumed by `#[panic_handler]`")),
|
||||
Some("subsumed by `#[panic_handler]`"), 53619),
|
||||
/// Allows `extern "platform-intrinsic" { ... }`.
|
||||
(removed, platform_intrinsics, "1.4.0", Some(27731),
|
||||
Some("SIMD intrinsics use the regular intrinsics ABI now")),
|
||||
(removed, platform_intrinsics, "1.78.0", Some(27731),
|
||||
Some("SIMD intrinsics use the regular intrinsics ABI now"), 121516),
|
||||
/// Allows using `#![plugin(myplugin)]`.
|
||||
(removed, plugin, "1.75.0", Some(29597),
|
||||
Some("plugins are no longer supported")),
|
||||
Some("plugins are no longer supported"), 116412),
|
||||
/// Allows using `#[plugin_registrar]` on functions.
|
||||
(removed, plugin_registrar, "1.54.0", Some(29597),
|
||||
Some("plugins are no longer supported")),
|
||||
(removed, plugin_registrar, "1.75.0", Some(29597),
|
||||
Some("plugins are no longer supported"), 116412),
|
||||
/// Allows exhaustive integer pattern matching with `usize::MAX`/`isize::MIN`/`isize::MAX`.
|
||||
(removed, precise_pointer_size_matching, "1.32.0", Some(56354),
|
||||
Some("removed in favor of half-open ranges")),
|
||||
(removed, precise_pointer_size_matching, "1.76.0", Some(56354),
|
||||
Some("removed in favor of half-open ranges"), 118598),
|
||||
(removed, pref_align_of, "CURRENT_RUSTC_VERSION", Some(91971),
|
||||
Some("removed due to marginal use and inducing compiler complications")),
|
||||
(removed, proc_macro_expr, "1.27.0", Some(54727),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121),
|
||||
(removed, proc_macro_gen, "1.27.0", Some(54727),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121),
|
||||
(removed, proc_macro_mod, "1.27.0", Some(54727),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121),
|
||||
(removed, proc_macro_non_items, "1.27.0", Some(54727),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121),
|
||||
(removed, pub_macro_rules, "1.53.0", Some(78855),
|
||||
Some("removed due to being incomplete, in particular it does not work across crates")),
|
||||
(removed, pushpop_unsafe, "1.2.0", None, None),
|
||||
(removed, quad_precision_float, "1.0.0", None, None),
|
||||
(removed, quote, "1.33.0", Some(29601), None),
|
||||
(removed, ref_pat_everywhere, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024")),
|
||||
(removed, ref_pat_everywhere, "1.80.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024"), 125168),
|
||||
(removed, reflect, "1.0.0", Some(27749), None),
|
||||
/// Allows using the `#[register_attr]` attribute.
|
||||
(removed, register_attr, "1.65.0", Some(66080),
|
||||
Some("removed in favor of `#![register_tool]`")),
|
||||
Some("removed in favor of `#![register_tool]`"), 66070),
|
||||
(removed, rust_2018_preview, "1.76.0", None,
|
||||
Some("2018 Edition preview is no longer relevant")),
|
||||
/// Allows using the macros:
|
||||
/// + `__diagnostic_used`
|
||||
/// + `__register_diagnostic`
|
||||
/// +`__build_diagnostic_array`
|
||||
(removed, rustc_diagnostic_macros, "1.38.0", None, None),
|
||||
(removed, rustc_diagnostic_macros, "1.38.0", None, None, 64139),
|
||||
/// Allows identifying crates that contain sanitizer runtimes.
|
||||
(removed, sanitizer_runtime, "1.17.0", None, None),
|
||||
(removed, sanitizer_runtime, "1.17.0", None, None, 65241),
|
||||
(removed, simd, "1.0.0", Some(27731), Some("removed in favor of `#[repr(simd)]`")),
|
||||
/// Allows using `#[start]` on a function indicating that it is the program entrypoint.
|
||||
(removed, start, "1.0.0", Some(29633), Some("not portable enough and never RFC'd")),
|
||||
(removed, start, "1.86.0", Some(29633), Some("not portable enough and never RFC'd"), 134299),
|
||||
/// Allows `#[link(kind = "static-nobundle", ...)]`.
|
||||
(removed, static_nobundle, "1.16.0", Some(37403),
|
||||
Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)),
|
||||
(removed, static_nobundle, "1.63.0", Some(37403),
|
||||
Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#), 95818),
|
||||
(removed, struct_inherit, "1.0.0", None, None),
|
||||
(removed, test_removed_feature, "1.0.0", None, None),
|
||||
/// Allows using items which are missing stability attributes
|
||||
(removed, unmarked_api, "1.0.0", None, None),
|
||||
/// Allows unnamed fields of struct and union type
|
||||
(removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")),
|
||||
(removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign"), 131045),
|
||||
(removed, unsafe_no_drop_flag, "1.0.0", None, None),
|
||||
(removed, unsized_tuple_coercion, "1.87.0", Some(42877),
|
||||
Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")),
|
||||
Some("The feature restricts possible layouts for tuples, and this restriction is not worth it."), 137728),
|
||||
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
|
||||
(removed, untagged_unions, "1.13.0", Some(55149),
|
||||
Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),
|
||||
(removed, untagged_unions, "1.64.0", Some(55149),
|
||||
Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more"), 97995),
|
||||
/// Allows `#[unwind(..)]`.
|
||||
///
|
||||
/// Permits specifying whether a function should permit unwinding or abort on unwind.
|
||||
(removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead")),
|
||||
(removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead"), 86155),
|
||||
(removed, visible_private_types, "1.0.0", None, None),
|
||||
/// Allows `extern "wasm" fn`
|
||||
(removed, wasm_abi, "1.81.0", Some(83788),
|
||||
Some("non-standard wasm ABI is no longer supported")),
|
||||
Some("non-standard wasm ABI is no longer supported"), 127605),
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
|
|
|
|||
|
|
@ -546,8 +546,6 @@ declare_features! (
|
|||
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
|
||||
/// Allows using `pointer` and `reference` in intra-doc links
|
||||
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
|
||||
// Allows using the `kl` and `widekl` target features and the associated intrinsics
|
||||
(unstable, keylocker_x86, "1.86.0", Some(134813)),
|
||||
// Allows setting the threshold for the `large_assignments` lint.
|
||||
(unstable, large_assignments, "1.52.0", Some(83518)),
|
||||
/// Allow to have type alias types for inter-crate use.
|
||||
|
|
@ -627,8 +625,6 @@ declare_features! (
|
|||
(unstable, return_type_notation, "1.70.0", Some(109417)),
|
||||
/// Allows `extern "rust-cold"`.
|
||||
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
|
||||
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
|
||||
(unstable, sha512_sm_x86, "1.82.0", Some(126624)),
|
||||
/// Allows the use of SIMD types in functions declared in `extern` blocks.
|
||||
(unstable, simd_ffi, "1.0.0", Some(27731)),
|
||||
/// Allows specialization of implementations (RFC 1210).
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(track_path)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
self.param_env,
|
||||
ty::Binder::dummy(trait_ref),
|
||||
);
|
||||
if !self.infcx.predicate_may_hold(&obligation) {
|
||||
if !self.infcx.next_trait_solver() && !self.infcx.predicate_may_hold(&obligation) {
|
||||
debug!("overloaded_deref_ty: cannot match obligation");
|
||||
return None;
|
||||
}
|
||||
|
|
@ -184,17 +184,17 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
self.param_env,
|
||||
ty,
|
||||
) else {
|
||||
// We shouldn't have errors here, except for evaluate/fulfill mismatches,
|
||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||
// by design).
|
||||
// FIXME(-Znext-solver): This *actually* shouldn't happen then.
|
||||
// We shouldn't have errors here in the old solver, except for
|
||||
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
|
||||
return None;
|
||||
};
|
||||
let errors = ocx.select_where_possible();
|
||||
if !errors.is_empty() {
|
||||
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||
// by design).
|
||||
if self.infcx.next_trait_solver() {
|
||||
unreachable!();
|
||||
}
|
||||
// We shouldn't have errors here in the old solver, except for
|
||||
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
|
||||
debug!(?errors, "encountered errors while fulfilling");
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@ use std::ops::ControlFlow;
|
|||
use rustc_abi::FieldIdx;
|
||||
use rustc_attr_data_structures::ReprAttr::ReprPacked;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{EmissionGuarantee, MultiSpan};
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::{LangItem, Node, intravisit};
|
||||
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::{Obligation, ObligationCauseCode};
|
||||
use rustc_lint_defs::builtin::{
|
||||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
|
||||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
|
||||
UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
|
||||
};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
|
|
@ -24,6 +25,7 @@ use rustc_middle::ty::{
|
|||
TypeVisitable, TypeVisitableExt, fold_regions,
|
||||
};
|
||||
use rustc_session::lint::builtin::UNINHABITED_STATIC;
|
||||
use rustc_target::spec::{AbiMap, AbiMapping};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
|
||||
use rustc_trait_selection::traits;
|
||||
|
|
@ -35,25 +37,66 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
|
|||
use super::compare_impl_item::check_type_bounds;
|
||||
use super::*;
|
||||
|
||||
pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
|
||||
if !tcx.sess.target.is_abi_supported(abi) {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0570,
|
||||
"`{abi}` is not a supported ABI for the current target",
|
||||
)
|
||||
.emit();
|
||||
fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
|
||||
if let ExternAbi::Cdecl { unwind } = abi {
|
||||
let c_abi = ExternAbi::C { unwind };
|
||||
diag.help(format!("use `extern {c_abi}` instead",));
|
||||
} else if let ExternAbi::Stdcall { unwind } = abi {
|
||||
let c_abi = ExternAbi::C { unwind };
|
||||
let system_abi = ExternAbi::System { unwind };
|
||||
diag.help(format!(
|
||||
"if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \
|
||||
use `extern {system_abi}`"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
|
||||
// FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix
|
||||
// things like #86232.
|
||||
|
||||
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) {
|
||||
AbiMapping::Direct(..) => (),
|
||||
AbiMapping::Invalid => {
|
||||
let mut err = struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0570,
|
||||
"`{abi}` is not a supported ABI for the current target",
|
||||
);
|
||||
add_abi_diag_help(abi, &mut err);
|
||||
err.emit();
|
||||
}
|
||||
AbiMapping::Deprecated(..) => {
|
||||
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
||||
lint.primary_message("use of calling convention not supported on this target");
|
||||
add_abi_diag_help(abi, lint);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
|
||||
if !tcx.sess.target.is_abi_supported(abi) {
|
||||
tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
||||
lint.primary_message(format!(
|
||||
"the calling convention {abi} is not supported on this target"
|
||||
));
|
||||
});
|
||||
// This is always an FCW, even for `AbiMapping::Invalid`, since we started linting later than
|
||||
// in `check_abi` above.
|
||||
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) {
|
||||
AbiMapping::Direct(..) => (),
|
||||
// This is not a redundant match arm: these ABIs started linting after introducing
|
||||
// UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS already existed and we want to
|
||||
// avoid expanding the scope of that lint so it can move to a hard error sooner.
|
||||
AbiMapping::Deprecated(..) => {
|
||||
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
||||
lint.primary_message("use of calling convention not supported on this target");
|
||||
add_abi_diag_help(abi, lint);
|
||||
});
|
||||
}
|
||||
AbiMapping::Invalid => {
|
||||
tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
||||
lint.primary_message(format!(
|
||||
"the calling convention {abi} is not supported on this target"
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -812,7 +855,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
|
||||
return;
|
||||
};
|
||||
check_abi(tcx, it.span, abi);
|
||||
check_abi(tcx, it.hir_id(), it.span, abi);
|
||||
|
||||
for item in items {
|
||||
let def_id = item.id.owner_id.def_id;
|
||||
|
|
|
|||
|
|
@ -805,7 +805,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
||||
});
|
||||
let bound = (bound.upcast(tcx), span);
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the
|
||||
// new trait solver lands. This fixed an overflow in the old solver.
|
||||
// This may have performance implications, so please check perf when
|
||||
// removing it.
|
||||
// This was added in <https://github.com/rust-lang/rust/pull/123302>.
|
||||
if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {
|
||||
bounds.insert(0, bound);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,24 @@ hir_typeck_base_expression_double_dot_enable_default_field_values =
|
|||
add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields
|
||||
hir_typeck_base_expression_double_dot_remove = remove the `..` as all the fields are already present
|
||||
|
||||
hir_typeck_break_inside_closure =
|
||||
`{$name}` inside of a closure
|
||||
.label = cannot `{$name}` inside of a closure
|
||||
.closure_label = enclosing closure
|
||||
|
||||
hir_typeck_break_inside_coroutine =
|
||||
`{$name}` inside `{$kind}` {$source}
|
||||
.label = cannot `{$name}` inside `{$kind}` {$source}
|
||||
.coroutine_label = enclosing `{$kind}` {$source}
|
||||
|
||||
hir_typeck_break_non_loop =
|
||||
`break` with value from a `{$kind}` loop
|
||||
.label = can only break with a value inside `loop` or breakable block
|
||||
.label2 = you can't `break` with a value in a `{$kind}` loop
|
||||
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
|
||||
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
|
||||
|
||||
|
||||
hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
|
||||
[NONE] {""}
|
||||
[implement] , perhaps you need to implement it
|
||||
|
|
@ -64,6 +82,12 @@ hir_typeck_const_select_must_be_fn = this argument must be a function item
|
|||
.note = expected a function item, found {$ty}
|
||||
.help = consult the documentation on `const_eval_select` for more information
|
||||
|
||||
hir_typeck_continue_labeled_block =
|
||||
`continue` pointing to a labeled block
|
||||
.label = labeled blocks cannot be `continue`'d
|
||||
.block_label = labeled block the `continue` points to
|
||||
|
||||
|
||||
hir_typeck_convert_to_str = try converting the passed type into a `&str`
|
||||
|
||||
hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `{$expected}`
|
||||
|
|
@ -182,6 +206,19 @@ hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expecte
|
|||
hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}`
|
||||
hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}`
|
||||
|
||||
hir_typeck_outside_loop =
|
||||
`{$name}` outside of a loop{$is_break ->
|
||||
[true] {" or labeled block"}
|
||||
*[false] {""}
|
||||
}
|
||||
.label = cannot `{$name}` outside of a loop{$is_break ->
|
||||
[true] {" or labeled block"}
|
||||
*[false] {""}
|
||||
}
|
||||
|
||||
hir_typeck_outside_loop_suggestion = consider labeling this block to be able to break within it
|
||||
|
||||
|
||||
hir_typeck_params_not_allowed =
|
||||
referencing function parameters is not allowed in naked functions
|
||||
.help = follow the calling convention in asm block to use parameters
|
||||
|
|
@ -254,6 +291,13 @@ hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
|
|||
|
||||
hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
|
||||
|
||||
hir_typeck_unlabeled_cf_in_while_condition =
|
||||
`break` or `continue` with no label in the condition of a `while` loop
|
||||
.label = unlabeled `{$cf_type}` in the condition of a `while` loop
|
||||
|
||||
hir_typeck_unlabeled_in_labeled_block =
|
||||
unlabeled `{$cf_type}` inside of a labeled block
|
||||
.label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
|
||||
hir_typeck_use_is_empty =
|
||||
consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything
|
||||
|
||||
|
|
|
|||
|
|
@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let (def_id, args) = match *expected_ty.kind() {
|
||||
// FIXME: Could also check that the RPIT is not defined
|
||||
ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args),
|
||||
// FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
|
||||
// FIXME(-Znext-solver=no): Remove this branch once `replace_opaque_types_with_infer` is gone.
|
||||
ty::Infer(ty::TyVar(_)) => self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
|
|
|
|||
|
|
@ -260,7 +260,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> Result<Ty<'tcx>, Diag<'a>> {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
let expected = if self.next_trait_solver() {
|
||||
expected
|
||||
} else {
|
||||
self.resolve_vars_with_obligations(expected)
|
||||
};
|
||||
|
||||
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
|
||||
Ok(ty) => return Ok(ty),
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_ast::Label;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic,
|
||||
EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::ExprKind;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
|
||||
|
|
@ -721,6 +724,131 @@ pub(crate) struct TrivialCast<'tcx> {
|
|||
pub cast_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
pub(crate) struct BreakNonLoop<'a> {
|
||||
pub span: Span,
|
||||
pub head: Option<Span>,
|
||||
pub kind: &'a str,
|
||||
pub suggestion: String,
|
||||
pub loop_label: Option<Label>,
|
||||
pub break_label: Option<Label>,
|
||||
pub break_expr_kind: &'a ExprKind<'a>,
|
||||
pub break_expr_span: Span,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> {
|
||||
#[track_caller]
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
||||
let mut diag = Diag::new(dcx, level, fluent::hir_typeck_break_non_loop);
|
||||
diag.span(self.span);
|
||||
diag.code(E0571);
|
||||
diag.arg("kind", self.kind);
|
||||
diag.span_label(self.span, fluent::hir_typeck_label);
|
||||
if let Some(head) = self.head {
|
||||
diag.span_label(head, fluent::hir_typeck_label2);
|
||||
}
|
||||
diag.span_suggestion(
|
||||
self.span,
|
||||
fluent::hir_typeck_suggestion,
|
||||
self.suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if let (Some(label), None) = (self.loop_label, self.break_label) {
|
||||
match self.break_expr_kind {
|
||||
ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { segments: [segment], res: hir::def::Res::Err, .. },
|
||||
)) if label.ident.to_string() == format!("'{}", segment.ident) => {
|
||||
// This error is redundant, we will have already emitted a
|
||||
// suggestion to use the label when `segment` wasn't found
|
||||
// (hence the `Res::Err` check).
|
||||
diag.downgrade_to_delayed_bug();
|
||||
}
|
||||
_ => {
|
||||
diag.span_suggestion(
|
||||
self.break_expr_span,
|
||||
fluent::hir_typeck_break_expr_suggestion,
|
||||
label.ident,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_continue_labeled_block, code = E0696)]
|
||||
pub(crate) struct ContinueLabeledBlock {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_typeck_block_label)]
|
||||
pub block_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_break_inside_closure, code = E0267)]
|
||||
pub(crate) struct BreakInsideClosure<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_typeck_closure_label)]
|
||||
pub closure_span: Span,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_break_inside_coroutine, code = E0267)]
|
||||
pub(crate) struct BreakInsideCoroutine<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_typeck_coroutine_label)]
|
||||
pub coroutine_span: Span,
|
||||
pub name: &'a str,
|
||||
pub kind: &'a str,
|
||||
pub source: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_outside_loop, code = E0268)]
|
||||
pub(crate) struct OutsideLoop<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub spans: Vec<Span>,
|
||||
pub name: &'a str,
|
||||
pub is_break: bool,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: Option<OutsideLoopSuggestion>,
|
||||
}
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(hir_typeck_outside_loop_suggestion, applicability = "maybe-incorrect")]
|
||||
pub(crate) struct OutsideLoopSuggestion {
|
||||
#[suggestion_part(code = "'block: ")]
|
||||
pub block_span: Span,
|
||||
#[suggestion_part(code = " 'block")]
|
||||
pub break_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_unlabeled_in_labeled_block, code = E0695)]
|
||||
pub(crate) struct UnlabeledInLabeledBlock<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub cf_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_unlabeled_cf_in_while_condition, code = E0590)]
|
||||
pub(crate) struct UnlabeledCfInWhileCondition<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub cf_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_no_associated_item, code = E0599)]
|
||||
pub(crate) struct NoAssociatedItem {
|
||||
|
|
|
|||
|
|
@ -1436,8 +1436,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// in this case.
|
||||
#[instrument(level = "debug", skip(self, sp), ret)]
|
||||
pub(crate) fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = self.resolve_vars_with_obligations(ty);
|
||||
|
||||
if self.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
|
|
@ -1455,7 +1453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
self.resolve_vars_with_obligations(ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -412,9 +412,10 @@ pub(crate) struct LoweredTy<'tcx> {
|
|||
|
||||
impl<'tcx> LoweredTy<'tcx> {
|
||||
fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
|
||||
// FIXME(-Znext-solver): We're still figuring out how to best handle
|
||||
// normalization and this doesn't feel too great. We should look at this
|
||||
// code again before stabilizing it.
|
||||
// FIXME(-Znext-solver=no): This is easier than requiring all uses of `LoweredTy`
|
||||
// to call `try_structurally_resolve_type` instead. This seems like a lot of
|
||||
// effort, especially as we're still supporting the old solver. We may revisit
|
||||
// this in the future.
|
||||
let normalized = if fcx.next_trait_solver() {
|
||||
fcx.try_structurally_resolve_type(span, raw)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(never_type)]
|
||||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
mod _match;
|
||||
|
|
@ -30,6 +28,7 @@ mod fallback;
|
|||
mod fn_ctxt;
|
||||
mod gather_locals;
|
||||
mod intrinsicck;
|
||||
mod loops;
|
||||
mod method;
|
||||
mod naked_functions;
|
||||
mod op;
|
||||
|
|
@ -150,7 +149,8 @@ fn typeck_with_inspect<'tcx>(
|
|||
tcx.fn_sig(def_id).instantiate_identity()
|
||||
};
|
||||
|
||||
check_abi(tcx, span, fn_sig.abi());
|
||||
check_abi(tcx, id, span, fn_sig.abi());
|
||||
loops::check(tcx, def_id, body);
|
||||
|
||||
// Compute the function signature from point of view of inside the fn.
|
||||
let mut fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
|
||||
|
|
@ -191,6 +191,8 @@ fn typeck_with_inspect<'tcx>(
|
|||
tcx.type_of(def_id).instantiate_identity()
|
||||
};
|
||||
|
||||
loops::check(tcx, def_id, body);
|
||||
|
||||
let expected_type = fcx.normalize(body.value.span, expected_type);
|
||||
|
||||
let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ use std::fmt;
|
|||
|
||||
use Context::*;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Destination, Node};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
|
|
@ -73,17 +73,17 @@ struct CheckLoopVisitor<'tcx> {
|
|||
block_breaks: BTreeMap<Span, BlockInfo>,
|
||||
}
|
||||
|
||||
fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) {
|
||||
let mut check =
|
||||
CheckLoopVisitor { tcx, cx_stack: vec![Normal], block_breaks: Default::default() };
|
||||
tcx.hir_visit_item_likes_in_module(module_def_id, &mut check);
|
||||
let cx = match tcx.def_kind(def_id) {
|
||||
DefKind::AnonConst => AnonConst,
|
||||
_ => Fn,
|
||||
};
|
||||
check.with_context(cx, |v| v.visit_body(body));
|
||||
check.report_outside_loop_error();
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { check_mod_loops, ..*providers };
|
||||
}
|
||||
|
||||
impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
|
||||
type NestedFilter = nested_filter::OnlyBodies;
|
||||
|
||||
|
|
@ -91,33 +91,14 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
|
|||
self.tcx
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
|
||||
self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
|
||||
fn visit_anon_const(&mut self, _: &'hir hir::AnonConst) {
|
||||
// Typecked on its own.
|
||||
}
|
||||
|
||||
fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) {
|
||||
self.with_context(ConstBlock, |v| intravisit::walk_inline_const(v, c));
|
||||
}
|
||||
|
||||
fn visit_fn(
|
||||
&mut self,
|
||||
fk: hir::intravisit::FnKind<'hir>,
|
||||
fd: &'hir hir::FnDecl<'hir>,
|
||||
b: hir::BodyId,
|
||||
_: Span,
|
||||
id: LocalDefId,
|
||||
) {
|
||||
self.with_context(Fn, |v| intravisit::walk_fn(v, fk, fd, b, id));
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'hir hir::TraitItem<'hir>) {
|
||||
self.with_context(Fn, |v| intravisit::walk_trait_item(v, trait_item));
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'hir hir::ImplItem<'hir>) {
|
||||
self.with_context(Fn, |v| intravisit::walk_impl_item(v, impl_item));
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||
match e.kind {
|
||||
hir::ExprKind::If(cond, then, else_opt) => {
|
||||
|
|
@ -1913,8 +1913,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
ty::Binder::dummy(trait_ref),
|
||||
);
|
||||
|
||||
// FIXME(-Znext-solver): We only need this hack to deal with fatal
|
||||
// overflow in the old solver.
|
||||
// We only need this hack to deal with fatal overflow in the old solver.
|
||||
if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation)
|
||||
{
|
||||
ocx.register_obligation(obligation);
|
||||
|
|
@ -1955,17 +1954,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(-Znext-solver): See the linked issue below.
|
||||
// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>
|
||||
// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>.
|
||||
//
|
||||
// In the new solver, check the well-formedness of the return type.
|
||||
// This emulates, in a way, the predicates that fall out of
|
||||
// normalizing the return type in the old solver.
|
||||
//
|
||||
// We alternatively could check the predicates of the method itself hold,
|
||||
// but we intentionally do not do this in the old solver b/c of cycles,
|
||||
// and doing it in the new solver would be stronger. This should be fixed
|
||||
// in the future, since it likely leads to much better method winnowing.
|
||||
// FIXME(-Znext-solver): We alternatively could check the predicates of
|
||||
// the method itself hold, but we intentionally do not do this in the old
|
||||
// solver b/c of cycles, and doing it in the new solver would be stronger.
|
||||
// This should be fixed in the future, since it likely leads to much better
|
||||
// method winnowing.
|
||||
if let Some(xform_ret_ty) = xform_ret_ty
|
||||
&& self.infcx.next_trait_solver()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3494,7 +3494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
trait_in_other_version_found = self
|
||||
.detect_and_explain_multiple_crate_versions(
|
||||
.detect_and_explain_multiple_crate_versions_of_trait_item(
|
||||
err,
|
||||
pick.item.def_id,
|
||||
rcvr.hir_id,
|
||||
|
|
@ -3701,12 +3701,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// same crate.
|
||||
|
||||
let rcvr_ty = self.node_ty_opt(ty.hir_id);
|
||||
trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions(
|
||||
err,
|
||||
assoc.def_id,
|
||||
ty.hir_id,
|
||||
rcvr_ty,
|
||||
);
|
||||
trait_in_other_version_found = self
|
||||
.detect_and_explain_multiple_crate_versions_of_trait_item(
|
||||
err,
|
||||
assoc.def_id,
|
||||
ty.hir_id,
|
||||
rcvr_ty,
|
||||
);
|
||||
}
|
||||
if !trait_in_other_version_found
|
||||
&& self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true)
|
||||
|
|
@ -4098,7 +4099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn detect_and_explain_multiple_crate_versions(
|
||||
fn detect_and_explain_multiple_crate_versions_of_trait_item(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
item_def_id: DefId,
|
||||
|
|
@ -4111,6 +4112,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
let trait_def_id = self.tcx.parent(item_def_id);
|
||||
if !self.tcx.is_trait(trait_def_id) {
|
||||
return false;
|
||||
}
|
||||
let krate = self.tcx.crate_name(trait_def_id.krate);
|
||||
let name = self.tcx.item_name(trait_def_id);
|
||||
let candidates: Vec<_> = traits
|
||||
|
|
|
|||
|
|
@ -198,8 +198,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||
// This may actually be reachable. If so, we should convert
|
||||
// this to a proper error/consider whether we should detect
|
||||
// this somewhere else.
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}"
|
||||
"unexpected overflowed when processing region obligations: {my_region_obligations:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,6 +238,9 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
|
|||
fn tag() -> &'static str {
|
||||
"TyVidEqKey"
|
||||
}
|
||||
fn order_roots(a: Self, _: &Self::Value, b: Self, _: &Self::Value) -> Option<(Self, Self)> {
|
||||
if a.vid.as_u32() < b.vid.as_u32() { Some((a, b)) } else { Some((b, a)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@ impl<'tcx> UnifyKey for ConstVidKey<'tcx> {
|
|||
fn tag() -> &'static str {
|
||||
"ConstVidKey"
|
||||
}
|
||||
fn order_roots(a: Self, _: &Self::Value, b: Self, _: &Self::Value) -> Option<(Self, Self)> {
|
||||
if a.vid.as_u32() < b.vid.as_u32() { Some((a, b)) } else { Some((b, a)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(iterator_try_collect)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![recursion_limit = "512"] // For rustdoc
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe;
|
|||
use rustc_query_impl::QueryCtxt;
|
||||
use rustc_query_system::query::print_query_stack;
|
||||
use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
|
||||
use rustc_session::filesearch::sysroot_candidates;
|
||||
use rustc_session::filesearch::sysroot_with_fallback;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
|
||||
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
|
||||
|
|
@ -442,8 +442,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
|
||||
|
||||
let bundle = match rustc_errors::fluent_bundle(
|
||||
config.opts.sysroot.clone(),
|
||||
sysroot_candidates().to_vec(),
|
||||
sysroot_with_fallback(&config.opts.sysroot),
|
||||
config.opts.unstable_opts.translate_lang.clone(),
|
||||
config.opts.unstable_opts.translate_additional_ftl.as_deref(),
|
||||
config.opts.unstable_opts.translate_directionality_markers,
|
||||
|
|
|
|||
|
|
@ -954,7 +954,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
tcx.ensure_ok().exportable_items(LOCAL_CRATE);
|
||||
tcx.ensure_ok().stable_order_of_exportable_impls(LOCAL_CRATE);
|
||||
tcx.par_hir_for_each_module(|module| {
|
||||
tcx.ensure_ok().check_mod_loops(module);
|
||||
tcx.ensure_ok().check_mod_attrs(module);
|
||||
tcx.ensure_ok().check_mod_unstable_api_usage(module);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::{env, iter, thread};
|
||||
use std::{env, thread};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
|
|
@ -12,7 +12,6 @@ use rustc_metadata::{DylibError, load_symbol_from_dylib};
|
|||
use rustc_middle::ty::CurrentGcx;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_tuple};
|
||||
use rustc_session::filesearch::sysroot_candidates;
|
||||
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
|
||||
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
|
||||
use rustc_session::{EarlyDiagCtxt, Session, filesearch};
|
||||
|
|
@ -346,14 +345,10 @@ pub fn rustc_path<'a>() -> Option<&'a Path> {
|
|||
}
|
||||
|
||||
fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
|
||||
sysroot_candidates().iter().find_map(|sysroot| {
|
||||
let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") {
|
||||
"rustc.exe"
|
||||
} else {
|
||||
"rustc"
|
||||
});
|
||||
candidate.exists().then_some(candidate)
|
||||
})
|
||||
let candidate = filesearch::get_or_default_sysroot()
|
||||
.join(bin_path)
|
||||
.join(if cfg!(target_os = "windows") { "rustc.exe" } else { "rustc" });
|
||||
candidate.exists().then_some(candidate)
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
|
|
@ -374,10 +369,10 @@ fn get_codegen_sysroot(
|
|||
);
|
||||
|
||||
let target = host_tuple();
|
||||
let sysroot_candidates = sysroot_candidates();
|
||||
let sysroot_candidates = filesearch::sysroot_with_fallback(&sysroot);
|
||||
|
||||
let sysroot = iter::once(sysroot)
|
||||
.chain(sysroot_candidates.iter().map(<_>::as_ref))
|
||||
let sysroot = sysroot_candidates
|
||||
.iter()
|
||||
.map(|sysroot| {
|
||||
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
|
|||
// the AST struct that they wrap (e.g. an item)
|
||||
self.with_lint_attrs(s.id, s.attrs(), |cx| {
|
||||
lint_callback!(cx, check_stmt, s);
|
||||
cx.check_id(s.id);
|
||||
});
|
||||
// The visitor for the AST struct wrapped
|
||||
// by the statement (e.g. `Item`) will call
|
||||
|
|
@ -147,7 +146,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
|
|||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId) {
|
||||
lint_callback!(self, check_fn, fk, span, id);
|
||||
self.check_id(id);
|
||||
ast_visit::walk_fn(self, fk);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -599,7 +599,6 @@ fn register_builtins(store: &mut LintStore) {
|
|||
"converted into hard error, see PR #125380 \
|
||||
<https://github.com/rust-lang/rust/pull/125380> for more information",
|
||||
);
|
||||
store.register_removed("unsupported_calling_conventions", "converted into hard error");
|
||||
store.register_removed(
|
||||
"cenum_impl_drop_cast",
|
||||
"converted into hard error, \
|
||||
|
|
|
|||
|
|
@ -3621,6 +3621,54 @@ declare_lint! {
|
|||
crate_level_only
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unsupported_calling_conventions` lint is output whenever there is a use of the
|
||||
/// `stdcall`, `fastcall`, and `cdecl` calling conventions (or their unwind
|
||||
/// variants) on targets that cannot meaningfully be supported for the requested target.
|
||||
///
|
||||
/// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc
|
||||
/// code, because this calling convention was never specified for those targets.
|
||||
///
|
||||
/// Historically MSVC toolchains have fallen back to the regular C calling convention for
|
||||
/// targets other than x86, but Rust doesn't really see a similar need to introduce a similar
|
||||
/// hack across many more targets.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,ignore (needs specific targets)
|
||||
/// extern "stdcall" fn stdcall() {}
|
||||
/// ```
|
||||
///
|
||||
/// This will produce:
|
||||
///
|
||||
/// ```text
|
||||
/// warning: use of calling convention not supported on this target
|
||||
/// --> $DIR/unsupported.rs:39:1
|
||||
/// |
|
||||
/// LL | extern "stdcall" fn stdcall() {}
|
||||
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
/// |
|
||||
/// = note: `#[warn(unsupported_calling_conventions)]` on by default
|
||||
/// = warning: this was previously accepted by the compiler but is being phased out;
|
||||
/// it will become a hard error in a future release!
|
||||
/// = note: for more information, see issue ...
|
||||
/// ```
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// On most of the targets the behaviour of `stdcall` and similar calling conventions is not
|
||||
/// defined at all, but was previously accepted due to a bug in the implementation of the
|
||||
/// compiler.
|
||||
pub UNSUPPORTED_CALLING_CONVENTIONS,
|
||||
Warn,
|
||||
"use of unsupported calling convention",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseError,
|
||||
report_in_deps: true,
|
||||
reference: "issue #137018 <https://github.com/rust-lang/rust/issues/137018>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unsupported_fn_ptr_calling_conventions` lint is output whenever there is a use of
|
||||
/// a target dependent calling convention on a target that does not support this calling
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#![feature(if_let_guard)]
|
||||
#![feature(never_type)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![feature(proc_macro_tracked_env)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,9 @@ metadata_raw_dylib_no_nul =
|
|||
metadata_raw_dylib_only_windows =
|
||||
link kind `raw-dylib` is only supported on Windows targets
|
||||
|
||||
metadata_raw_dylib_unsupported_abi =
|
||||
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
|
||||
|
||||
metadata_renaming_no_link =
|
||||
renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
|
||||
|
||||
|
|
@ -319,12 +322,6 @@ metadata_unknown_link_modifier =
|
|||
|
||||
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
|
||||
|
||||
metadata_unsupported_abi =
|
||||
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
|
||||
|
||||
metadata_unsupported_abi_i686 =
|
||||
ABI not supported by `#[link(kind = "raw-dylib")]` on i686
|
||||
|
||||
metadata_wasm_c_abi =
|
||||
older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88
|
||||
|
||||
|
|
|
|||
|
|
@ -300,15 +300,8 @@ pub struct NoLinkModOverride {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unsupported_abi_i686)]
|
||||
pub struct UnsupportedAbiI686 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unsupported_abi)]
|
||||
pub struct UnsupportedAbi {
|
||||
#[diag(metadata_raw_dylib_unsupported_abi)]
|
||||
pub struct RawDylibUnsupportedAbi {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -652,7 +652,13 @@ impl<'tcx> Collector<'tcx> {
|
|||
) -> DllImport {
|
||||
let span = self.tcx.def_span(item);
|
||||
|
||||
// this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs
|
||||
// This `extern` block should have been checked for general ABI support before, but let's
|
||||
// double-check that.
|
||||
assert!(self.tcx.sess.target.is_abi_supported(abi));
|
||||
|
||||
// This logic is similar to `AbiMap::canonize_abi` (in rustc_target/src/spec/abi_map.rs) but
|
||||
// we need more detail than those adjustments, and we can't support all ABIs that are
|
||||
// generally supported.
|
||||
let calling_convention = if self.tcx.sess.target.arch == "x86" {
|
||||
match abi {
|
||||
ExternAbi::C { .. } | ExternAbi::Cdecl { .. } => DllCallingConvention::C,
|
||||
|
|
@ -679,7 +685,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
|
||||
}
|
||||
_ => {
|
||||
self.tcx.dcx().emit_fatal(errors::UnsupportedAbiI686 { span });
|
||||
self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -688,7 +694,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
DllCallingConvention::C
|
||||
}
|
||||
_ => {
|
||||
self.tcx.dcx().emit_fatal(errors::UnsupportedAbi { span });
|
||||
self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
#![feature(round_char_boundary)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(try_trait_v2_yeet)]
|
||||
|
|
|
|||
|
|
@ -1531,8 +1531,6 @@ pub enum CastKind {
|
|||
///
|
||||
/// MIR is well-formed if the input and output types have different sizes,
|
||||
/// but running a transmute between differently-sized types is UB.
|
||||
///
|
||||
/// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`].
|
||||
Transmute,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -389,6 +389,7 @@ tcx_lifetime! {
|
|||
rustc_middle::ty::layout::FnAbiError,
|
||||
rustc_middle::ty::layout::LayoutError,
|
||||
rustc_middle::ty::ParamEnv,
|
||||
rustc_middle::ty::TypingEnv,
|
||||
rustc_middle::ty::Predicate,
|
||||
rustc_middle::ty::SymbolName,
|
||||
rustc_middle::ty::TraitRef,
|
||||
|
|
|
|||
|
|
@ -1115,11 +1115,6 @@ rustc_queries! {
|
|||
desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
/// Checks the loops in the module.
|
||||
query check_mod_loops(key: LocalModDefId) {
|
||||
desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_privacy(key: LocalModDefId) {
|
||||
desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) }
|
||||
}
|
||||
|
|
@ -1571,7 +1566,7 @@ rustc_queries! {
|
|||
/// Like `param_env`, but returns the `ParamEnv` after all opaque types have been
|
||||
/// replaced with their hidden type. This is used in the old trait solver
|
||||
/// when in `PostAnalysis` mode and should not be called directly.
|
||||
query param_env_normalized_for_post_analysis(def_id: DefId) -> ty::ParamEnv<'tcx> {
|
||||
query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> {
|
||||
desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ use crate::ty::{
|
|||
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
fn next_trait_solver_globally(self) -> bool {
|
||||
self.next_trait_solver_globally()
|
||||
}
|
||||
|
||||
type DefId = DefId;
|
||||
type LocalDefId = LocalDefId;
|
||||
type Span = Span;
|
||||
|
|
@ -179,6 +183,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
f(&mut *self.new_solver_evaluation_cache.lock())
|
||||
}
|
||||
|
||||
fn canonical_param_env_cache_get_or_insert<R>(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
f: impl FnOnce() -> ty::CanonicalParamEnvCacheEntry<Self>,
|
||||
from_entry: impl FnOnce(&ty::CanonicalParamEnvCacheEntry<Self>) -> R,
|
||||
) -> R {
|
||||
let mut cache = self.new_solver_canonical_param_env_cache.lock();
|
||||
let entry = cache.entry(param_env).or_insert_with(f);
|
||||
from_entry(entry)
|
||||
}
|
||||
|
||||
fn evaluation_is_concurrent(&self) -> bool {
|
||||
self.sess.threads() > 1
|
||||
}
|
||||
|
|
@ -1444,6 +1459,8 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
/// Caches the results of goal evaluation in the new solver.
|
||||
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
|
||||
pub new_solver_canonical_param_env_cache:
|
||||
Lock<FxHashMap<ty::ParamEnv<'tcx>, ty::CanonicalParamEnvCacheEntry<TyCtxt<'tcx>>>>,
|
||||
|
||||
pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
|
||||
|
||||
|
|
@ -1692,6 +1709,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
selection_cache: Default::default(),
|
||||
evaluation_cache: Default::default(),
|
||||
new_solver_evaluation_cache: Default::default(),
|
||||
new_solver_canonical_param_env_cache: Default::default(),
|
||||
canonical_param_env_cache: Default::default(),
|
||||
data_layout,
|
||||
alloc_map: interpret::AllocMap::new(),
|
||||
|
|
|
|||
|
|
@ -1116,10 +1116,7 @@ impl<'tcx> TypingEnv<'tcx> {
|
|||
}
|
||||
|
||||
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> {
|
||||
TypingEnv {
|
||||
typing_mode: TypingMode::PostAnalysis,
|
||||
param_env: tcx.param_env_normalized_for_post_analysis(def_id),
|
||||
}
|
||||
tcx.typing_env_normalized_for_post_analysis(def_id)
|
||||
}
|
||||
|
||||
/// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
|
||||
|
|
@ -1133,7 +1130,7 @@ impl<'tcx> TypingEnv<'tcx> {
|
|||
// No need to reveal opaques with the new solver enabled,
|
||||
// since we have lazy norm.
|
||||
let param_env = if tcx.next_trait_solver_globally() {
|
||||
ParamEnv::new(param_env.caller_bounds())
|
||||
param_env
|
||||
} else {
|
||||
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds()))
|
||||
};
|
||||
|
|
|
|||
|
|
@ -128,28 +128,20 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
|||
|
||||
let mut patch = MirPatch::new(body);
|
||||
|
||||
let (second_discriminant_temp, second_operand) = if opt_data.need_hoist_discriminant {
|
||||
let second_operand = if opt_data.need_hoist_discriminant {
|
||||
// create temp to store second discriminant in, `_s` in example above
|
||||
let second_discriminant_temp =
|
||||
patch.new_temp(opt_data.child_ty, opt_data.child_source.span);
|
||||
|
||||
patch.add_statement(
|
||||
parent_end,
|
||||
StatementKind::StorageLive(second_discriminant_temp),
|
||||
);
|
||||
|
||||
// create assignment of discriminant
|
||||
patch.add_assign(
|
||||
parent_end,
|
||||
Place::from(second_discriminant_temp),
|
||||
Rvalue::Discriminant(opt_data.child_place),
|
||||
);
|
||||
(
|
||||
Some(second_discriminant_temp),
|
||||
Operand::Move(Place::from(second_discriminant_temp)),
|
||||
)
|
||||
Operand::Move(Place::from(second_discriminant_temp))
|
||||
} else {
|
||||
(None, Operand::Copy(opt_data.child_place))
|
||||
Operand::Copy(opt_data.child_place)
|
||||
};
|
||||
|
||||
// create temp to store inequality comparison between the two discriminants, `_t` in
|
||||
|
|
@ -157,7 +149,6 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
|||
let nequal = BinOp::Ne;
|
||||
let comp_res_type = nequal.ty(tcx, parent_ty, opt_data.child_ty);
|
||||
let comp_temp = patch.new_temp(comp_res_type, opt_data.child_source.span);
|
||||
patch.add_statement(parent_end, StatementKind::StorageLive(comp_temp));
|
||||
|
||||
// create inequality comparison
|
||||
let comp_rvalue =
|
||||
|
|
@ -200,23 +191,6 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
|||
TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case),
|
||||
);
|
||||
|
||||
if let Some(second_discriminant_temp) = second_discriminant_temp {
|
||||
// generate StorageDead for the second_discriminant_temp not in use anymore
|
||||
patch.add_statement(
|
||||
parent_end,
|
||||
StatementKind::StorageDead(second_discriminant_temp),
|
||||
);
|
||||
}
|
||||
|
||||
// Generate a StorageDead for comp_temp in each of the targets, since we moved it into
|
||||
// the switch
|
||||
for bb in [false_case, true_case].iter() {
|
||||
patch.add_statement(
|
||||
Location { block: *bb, statement_index: 0 },
|
||||
StatementKind::StorageDead(comp_temp),
|
||||
);
|
||||
}
|
||||
|
||||
patch.apply(body);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
}
|
||||
false
|
||||
}
|
||||
// FIXME(-Znext-solver): Remove this hack when trait solver overflow can return an error.
|
||||
// FIXME(-Znext-solver=no): Remove this hack when trait solver overflow can return an error.
|
||||
// In code like that pointed out in #128887, the type complexity we ask the solver to deal with
|
||||
// grows as we recurse into the call graph. If we use the same recursion limit here and in the
|
||||
// solver, the solver hits the limit first and emits a fatal error. But if we use a reduced
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@
|
|||
#![feature(file_buffered)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(never_type)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(vec_deque_pop_if)]
|
||||
#![feature(yeet_expr)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -1308,37 +1308,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
CastKind::Transmute => {
|
||||
if let MirPhase::Runtime(..) = self.body.phase {
|
||||
// Unlike `mem::transmute`, a MIR `Transmute` is well-formed
|
||||
// for any two `Sized` types, just potentially UB to run.
|
||||
// Unlike `mem::transmute`, a MIR `Transmute` is well-formed
|
||||
// for any two `Sized` types, just potentially UB to run.
|
||||
|
||||
if !self
|
||||
.tcx
|
||||
.normalize_erasing_regions(self.typing_env, op_ty)
|
||||
.is_sized(self.tcx, self.typing_env)
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot transmute from non-`Sized` type {op_ty}"),
|
||||
);
|
||||
}
|
||||
if !self
|
||||
.tcx
|
||||
.normalize_erasing_regions(self.typing_env, *target_type)
|
||||
.is_sized(self.tcx, self.typing_env)
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot transmute to non-`Sized` type {target_type:?}"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if !self
|
||||
.tcx
|
||||
.normalize_erasing_regions(self.typing_env, op_ty)
|
||||
.is_sized(self.tcx, self.typing_env)
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Transmute is not supported in non-runtime phase {:?}.",
|
||||
self.body.phase
|
||||
),
|
||||
format!("Cannot transmute from non-`Sized` type {op_ty}"),
|
||||
);
|
||||
}
|
||||
if !self
|
||||
.tcx
|
||||
.normalize_erasing_regions(self.typing_env, *target_type)
|
||||
.is_sized(self.tcx, self.typing_env)
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot transmute to non-`Sized` type {target_type:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
|
|||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::solve::{Goal, QueryInput};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, Flags, InferCtxtLike, Interner,
|
||||
TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalTyVarKind, CanonicalVarKind,
|
||||
Flags, InferCtxtLike, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
|
|
@ -100,6 +101,76 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
Canonical { max_universe, variables, value }
|
||||
}
|
||||
|
||||
fn canonicalize_param_env(
|
||||
delegate: &'a D,
|
||||
variables: &'a mut Vec<I::GenericArg>,
|
||||
param_env: I::ParamEnv,
|
||||
) -> (I::ParamEnv, HashMap<I::GenericArg, usize>, Vec<CanonicalVarKind<I>>) {
|
||||
if !param_env.has_type_flags(NEEDS_CANONICAL) {
|
||||
return (param_env, Default::default(), Vec::new());
|
||||
}
|
||||
|
||||
// Check whether we can use the global cache for this param_env. As we only use
|
||||
// the `param_env` itself as the cache key, considering any additional information
|
||||
// durnig its canonicalization would be incorrect. We always canonicalize region
|
||||
// inference variables in a separate universe, so these are fine. However, we do
|
||||
// track the universe of type and const inference variables so these must not be
|
||||
// globally cached. We don't rely on any additional information when canonicalizing
|
||||
// placeholders.
|
||||
if !param_env.has_non_region_infer() {
|
||||
delegate.cx().canonical_param_env_cache_get_or_insert(
|
||||
param_env,
|
||||
|| {
|
||||
let mut variables = Vec::new();
|
||||
let mut env_canonicalizer = Canonicalizer {
|
||||
delegate,
|
||||
canonicalize_mode: CanonicalizeMode::Input { keep_static: true },
|
||||
|
||||
variables: &mut variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
cache: Default::default(),
|
||||
};
|
||||
let param_env = param_env.fold_with(&mut env_canonicalizer);
|
||||
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
|
||||
CanonicalParamEnvCacheEntry {
|
||||
param_env,
|
||||
variable_lookup_table: env_canonicalizer.variable_lookup_table,
|
||||
var_kinds: env_canonicalizer.var_kinds,
|
||||
variables,
|
||||
}
|
||||
},
|
||||
|&CanonicalParamEnvCacheEntry {
|
||||
param_env,
|
||||
variables: ref cache_variables,
|
||||
ref variable_lookup_table,
|
||||
ref var_kinds,
|
||||
}| {
|
||||
debug_assert!(variables.is_empty());
|
||||
variables.extend(cache_variables.iter().copied());
|
||||
(param_env, variable_lookup_table.clone(), var_kinds.clone())
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let mut env_canonicalizer = Canonicalizer {
|
||||
delegate,
|
||||
canonicalize_mode: CanonicalizeMode::Input { keep_static: true },
|
||||
|
||||
variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
cache: Default::default(),
|
||||
};
|
||||
let param_env = param_env.fold_with(&mut env_canonicalizer);
|
||||
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
|
||||
(param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds)
|
||||
}
|
||||
}
|
||||
|
||||
/// When canonicalizing query inputs, we keep `'static` in the `param_env`
|
||||
/// but erase it everywhere else. We generally don't want to depend on region
|
||||
/// identity, so while it should not matter whether `'static` is kept in the
|
||||
|
|
@ -114,37 +185,17 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
input: QueryInput<I, P>,
|
||||
) -> ty::Canonical<I, QueryInput<I, P>> {
|
||||
// First canonicalize the `param_env` while keeping `'static`
|
||||
let mut env_canonicalizer = Canonicalizer {
|
||||
delegate,
|
||||
canonicalize_mode: CanonicalizeMode::Input { keep_static: true },
|
||||
|
||||
variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
cache: Default::default(),
|
||||
};
|
||||
|
||||
let param_env = input.goal.param_env;
|
||||
let param_env = if param_env.has_type_flags(NEEDS_CANONICAL) {
|
||||
param_env.fold_with(&mut env_canonicalizer)
|
||||
} else {
|
||||
param_env
|
||||
};
|
||||
|
||||
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
|
||||
let (param_env, variable_lookup_table, var_kinds) =
|
||||
Canonicalizer::canonicalize_param_env(delegate, variables, input.goal.param_env);
|
||||
// Then canonicalize the rest of the input without keeping `'static`
|
||||
// while *mostly* reusing the canonicalizer from above.
|
||||
let mut rest_canonicalizer = Canonicalizer {
|
||||
delegate,
|
||||
canonicalize_mode: CanonicalizeMode::Input { keep_static: false },
|
||||
|
||||
variables: env_canonicalizer.variables,
|
||||
// We're able to reuse the `variable_lookup_table` as whether or not
|
||||
// it already contains an entry for `'static` does not matter.
|
||||
variable_lookup_table: env_canonicalizer.variable_lookup_table,
|
||||
var_kinds: env_canonicalizer.var_kinds,
|
||||
variables,
|
||||
variable_lookup_table,
|
||||
var_kinds,
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
// We do not reuse the cache as it may contain entries whose canonicalized
|
||||
|
|
|
|||
|
|
@ -237,8 +237,8 @@ where
|
|||
return None;
|
||||
}
|
||||
|
||||
// FIXME(-Znext-solver): We should instead try to find a `Certainty::Yes` response with
|
||||
// a subset of the constraints that all the other responses have.
|
||||
// FIXME(-Znext-solver): Add support to merge region constraints in
|
||||
// responses to deal with trait-system-refactor-initiative#27.
|
||||
let one = responses[0];
|
||||
if responses[1..].iter().all(|&resp| resp == one) {
|
||||
return Some(one);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ where
|
|||
// and we tag the impl bounds with `GoalSource::ImplWhereBound`?
|
||||
// Right now this includes both the impl and the assoc item where bounds,
|
||||
// and I don't think the assoc item where-bounds are allowed to be coinductive.
|
||||
//
|
||||
// Projecting to the IAT also "steps out the impl contructor", so we would have
|
||||
// to be very careful when changing the impl where-clauses to be productive.
|
||||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
cx.predicates_of(inherent.def_id)
|
||||
|
|
|
|||
|
|
@ -235,7 +235,11 @@ where
|
|||
.predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(cx, goal.predicate.trait_ref.args)
|
||||
.map(|p| goal.with(cx, p));
|
||||
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
|
||||
// While you could think of trait aliases to have a single builtin impl
|
||||
// which uses its implied trait bounds as where-clauses, using
|
||||
// `GoalSource::ImplWhereClause` here would be incorrect, as we also
|
||||
// impl them, which means we're "stepping out of the impl constructor"
|
||||
// again. To handle this, we treat these cycles as ambiguous for now.
|
||||
ecx.add_goals(GoalSource::Misc, nested_obligations);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#![feature(debug_closure_helpers)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(string_from_utf8_lossy_owned)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -1520,22 +1520,20 @@ impl<'a> Parser<'a> {
|
|||
Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
|
||||
} else if this.token_uninterpolated_span().at_least_rust_2018() {
|
||||
// `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||
let at_async = this.check_keyword(exp!(Async));
|
||||
// check for `gen {}` and `gen move {}`
|
||||
// or `async gen {}` and `async gen move {}`
|
||||
// FIXME: (async) gen closures aren't yet parsed.
|
||||
// FIXME(gen_blocks): Parse `gen async` and suggest swap
|
||||
if this.token_uninterpolated_span().at_least_rust_2024()
|
||||
// check for `gen {}` and `gen move {}`
|
||||
// or `async gen {}` and `async gen move {}`
|
||||
&& (this.is_gen_block(kw::Gen, 0)
|
||||
|| (this.check_keyword(exp!(Async)) && this.is_gen_block(kw::Gen, 1)))
|
||||
&& this.is_gen_block(kw::Gen, at_async as usize)
|
||||
{
|
||||
// FIXME: (async) gen closures aren't yet parsed.
|
||||
this.parse_gen_block()
|
||||
} else if this.check_keyword(exp!(Async)) {
|
||||
// FIXME(gen_blocks): Parse `gen async` and suggest swap
|
||||
if this.is_gen_block(kw::Async, 0) {
|
||||
// Check for `async {` and `async move {`,
|
||||
this.parse_gen_block()
|
||||
} else {
|
||||
this.parse_expr_closure()
|
||||
}
|
||||
// Check for `async {` and `async move {`,
|
||||
} else if this.is_gen_block(kw::Async, 0) {
|
||||
this.parse_gen_block()
|
||||
} else if at_async {
|
||||
this.parse_expr_closure()
|
||||
} else if this.eat_keyword_noexpect(kw::Await) {
|
||||
this.recover_incorrect_await_syntax(lo)
|
||||
} else {
|
||||
|
|
@ -2407,6 +2405,14 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
if let ClosureBinder::NotPresent = binder
|
||||
&& coroutine_kind.is_some()
|
||||
{
|
||||
// coroutine closures and generators can have the same qualifiers, so we might end up
|
||||
// in here if there is a missing `|` but also no `{`. Adjust the expectations in that case.
|
||||
self.expected_token_types.insert(TokenType::OpenBrace);
|
||||
}
|
||||
|
||||
let capture_clause = self.parse_capture_clause()?;
|
||||
let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
|
||||
let decl_hi = self.prev_token.span;
|
||||
|
|
|
|||
|
|
@ -56,23 +56,6 @@ passes_autodiff_attr =
|
|||
passes_both_ffi_const_and_pure =
|
||||
`#[ffi_const]` function cannot be `#[ffi_pure]`
|
||||
|
||||
passes_break_inside_closure =
|
||||
`{$name}` inside of a closure
|
||||
.label = cannot `{$name}` inside of a closure
|
||||
.closure_label = enclosing closure
|
||||
|
||||
passes_break_inside_coroutine =
|
||||
`{$name}` inside `{$kind}` {$source}
|
||||
.label = cannot `{$name}` inside `{$kind}` {$source}
|
||||
.coroutine_label = enclosing `{$kind}` {$source}
|
||||
|
||||
passes_break_non_loop =
|
||||
`break` with value from a `{$kind}` loop
|
||||
.label = can only break with a value inside `loop` or breakable block
|
||||
.label2 = you can't `break` with a value in a `{$kind}` loop
|
||||
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
|
||||
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
|
||||
|
||||
passes_cannot_stabilize_deprecated =
|
||||
an API can't be stabilized after it is deprecated
|
||||
.label = invalid version
|
||||
|
|
@ -103,10 +86,6 @@ passes_const_stable_not_stable =
|
|||
attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
|
||||
.label = attribute specified here
|
||||
|
||||
passes_continue_labeled_block =
|
||||
`continue` pointing to a labeled block
|
||||
.label = labeled blocks cannot be `continue`'d
|
||||
.block_label = labeled block the `continue` points to
|
||||
|
||||
passes_coroutine_on_non_closure =
|
||||
attribute should be applied to closures
|
||||
|
|
@ -574,17 +553,6 @@ passes_optimize_invalid_target =
|
|||
passes_outer_crate_level_attr =
|
||||
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
|
||||
passes_outside_loop =
|
||||
`{$name}` outside of a loop{$is_break ->
|
||||
[true] {" or labeled block"}
|
||||
*[false] {""}
|
||||
}
|
||||
.label = cannot `{$name}` outside of a loop{$is_break ->
|
||||
[true] {" or labeled block"}
|
||||
*[false] {""}
|
||||
}
|
||||
|
||||
passes_outside_loop_suggestion = consider labeling this block to be able to break within it
|
||||
|
||||
passes_panic_unwind_without_std =
|
||||
unwinding panics are not supported without std
|
||||
|
|
@ -752,14 +720,6 @@ passes_unknown_lang_item =
|
|||
definition of an unknown lang item: `{$name}`
|
||||
.label = definition of unknown lang item `{$name}`
|
||||
|
||||
passes_unlabeled_cf_in_while_condition =
|
||||
`break` or `continue` with no label in the condition of a `while` loop
|
||||
.label = unlabeled `{$cf_type}` in the condition of a `while` loop
|
||||
|
||||
passes_unlabeled_in_labeled_block =
|
||||
unlabeled `{$cf_type}` inside of a labeled block
|
||||
.label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
|
||||
|
||||
passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
|
||||
.suggestion = if you are using features which are still unstable, change to using `{$implies}`
|
||||
.suggestion_remove = if you are using features which are now stable, remove this line
|
||||
|
|
|
|||
|
|
@ -132,7 +132,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
target,
|
||||
attrs,
|
||||
),
|
||||
_ => {
|
||||
Attribute::Parsed(AttributeKind::AllowConstFnUnstable { .. }) => {
|
||||
self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Deprecation { .. }) => {
|
||||
self.check_deprecated(hir_id, attr, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */
|
||||
}
|
||||
Attribute::Parsed(
|
||||
AttributeKind::BodyStability { .. }
|
||||
| AttributeKind::ConstStabilityIndirect
|
||||
| AttributeKind::MacroTransparency(_),
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(_) => {
|
||||
match attr.path().as_slice() {
|
||||
[sym::diagnostic, sym::do_not_recommend, ..] => {
|
||||
self.check_do_not_recommend(attr.span(), hir_id, target, attr, item)
|
||||
|
|
@ -169,9 +184,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
self.check_rustc_layout_scalar_valid_range(attr, span, target)
|
||||
}
|
||||
[sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target),
|
||||
[sym::rustc_allow_const_fn_unstable, ..] => {
|
||||
self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
|
||||
}
|
||||
[sym::rustc_std_internal_symbol, ..] => {
|
||||
self.check_rustc_std_internal_symbol(attr, span, target)
|
||||
}
|
||||
|
|
@ -229,7 +241,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
|
||||
[sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target),
|
||||
[sym::no_mangle, ..] => self.check_no_mangle(hir_id, attr, span, target),
|
||||
[sym::deprecated, ..] => self.check_deprecated(hir_id, attr, span, target),
|
||||
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
|
||||
self.check_macro_use(hir_id, attr, target)
|
||||
}
|
||||
|
|
@ -283,7 +294,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| sym::pointee // FIXME(derive_coerce_pointee)
|
||||
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
|
||||
| sym::used // handled elsewhere to restrict to static items
|
||||
| sym::repr // handled elsewhere to restrict to type decls items
|
||||
| sym::instruction_set // broken on stable!!!
|
||||
| sym::windows_subsystem // broken on stable!!!
|
||||
| sym::patchable_function_entry // FIXME(patchable_function_entry)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::DEAD_CODE;
|
||||
use rustc_session::lint::{self, LintExpectationId};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{Symbol, kw, sym};
|
||||
|
||||
use crate::errors::{
|
||||
ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
|
||||
|
|
@ -793,6 +793,17 @@ fn check_item<'tcx>(
|
|||
// global_asm! is always live.
|
||||
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
|
||||
}
|
||||
DefKind::Const => {
|
||||
let item = tcx.hir_item(id);
|
||||
if let hir::ItemKind::Const(ident, ..) = item.kind
|
||||
&& ident.name == kw::Underscore
|
||||
{
|
||||
// `const _` is always live, as that syntax only exists for the side effects
|
||||
// of type checking and evaluating the constant expression, and marking them
|
||||
// as dead code would defeat that purpose.
|
||||
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use std::io::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_ast::Label;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
|
||||
MultiSpan, Subdiagnostic,
|
||||
};
|
||||
use rustc_hir::{self as hir, ExprKind, Target};
|
||||
use rustc_hir::Target;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{MainDefinition, Ty};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
|
|
@ -1071,131 +1070,6 @@ pub(crate) struct FeaturePreviouslyDeclared<'a> {
|
|||
pub prev_declared: &'a str,
|
||||
}
|
||||
|
||||
pub(crate) struct BreakNonLoop<'a> {
|
||||
pub span: Span,
|
||||
pub head: Option<Span>,
|
||||
pub kind: &'a str,
|
||||
pub suggestion: String,
|
||||
pub loop_label: Option<Label>,
|
||||
pub break_label: Option<Label>,
|
||||
pub break_expr_kind: &'a ExprKind<'a>,
|
||||
pub break_expr_span: Span,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> {
|
||||
#[track_caller]
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
||||
let mut diag = Diag::new(dcx, level, fluent::passes_break_non_loop);
|
||||
diag.span(self.span);
|
||||
diag.code(E0571);
|
||||
diag.arg("kind", self.kind);
|
||||
diag.span_label(self.span, fluent::passes_label);
|
||||
if let Some(head) = self.head {
|
||||
diag.span_label(head, fluent::passes_label2);
|
||||
}
|
||||
diag.span_suggestion(
|
||||
self.span,
|
||||
fluent::passes_suggestion,
|
||||
self.suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if let (Some(label), None) = (self.loop_label, self.break_label) {
|
||||
match self.break_expr_kind {
|
||||
ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { segments: [segment], res: hir::def::Res::Err, .. },
|
||||
)) if label.ident.to_string() == format!("'{}", segment.ident) => {
|
||||
// This error is redundant, we will have already emitted a
|
||||
// suggestion to use the label when `segment` wasn't found
|
||||
// (hence the `Res::Err` check).
|
||||
diag.downgrade_to_delayed_bug();
|
||||
}
|
||||
_ => {
|
||||
diag.span_suggestion(
|
||||
self.break_expr_span,
|
||||
fluent::passes_break_expr_suggestion,
|
||||
label.ident,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_continue_labeled_block, code = E0696)]
|
||||
pub(crate) struct ContinueLabeledBlock {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(passes_block_label)]
|
||||
pub block_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_break_inside_closure, code = E0267)]
|
||||
pub(crate) struct BreakInsideClosure<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(passes_closure_label)]
|
||||
pub closure_span: Span,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_break_inside_coroutine, code = E0267)]
|
||||
pub(crate) struct BreakInsideCoroutine<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(passes_coroutine_label)]
|
||||
pub coroutine_span: Span,
|
||||
pub name: &'a str,
|
||||
pub kind: &'a str,
|
||||
pub source: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_outside_loop, code = E0268)]
|
||||
pub(crate) struct OutsideLoop<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub spans: Vec<Span>,
|
||||
pub name: &'a str,
|
||||
pub is_break: bool,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: Option<OutsideLoopSuggestion>,
|
||||
}
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(passes_outside_loop_suggestion, applicability = "maybe-incorrect")]
|
||||
pub(crate) struct OutsideLoopSuggestion {
|
||||
#[suggestion_part(code = "'block: ")]
|
||||
pub block_span: Span,
|
||||
#[suggestion_part(code = " 'block")]
|
||||
pub break_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_unlabeled_in_labeled_block, code = E0695)]
|
||||
pub(crate) struct UnlabeledInLabeledBlock<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub cf_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_unlabeled_cf_in_while_condition, code = E0590)]
|
||||
pub(crate) struct UnlabeledCfInWhileCondition<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub cf_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_naked_functions_incompatible_attribute, code = E0736)]
|
||||
pub(crate) struct NakedFunctionIncompatibleAttribute {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,8 @@
|
|||
#![allow(internal_features)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use rustc_middle::util::Providers;
|
||||
|
|
@ -31,7 +29,6 @@ mod lang_items;
|
|||
pub mod layout_test;
|
||||
mod lib_features;
|
||||
mod liveness;
|
||||
pub mod loops;
|
||||
mod reachable;
|
||||
pub mod stability;
|
||||
mod upvars;
|
||||
|
|
@ -47,7 +44,6 @@ pub fn provide(providers: &mut Providers) {
|
|||
entry::provide(providers);
|
||||
lang_items::provide(providers);
|
||||
lib_features::provide(providers);
|
||||
loops::provide(providers);
|
||||
liveness::provide(providers);
|
||||
reachable::provide(providers);
|
||||
stability::provide(providers);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(min_specialization)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{env, fs};
|
||||
|
||||
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
|
||||
use rustc_fs_util::try_canonicalize;
|
||||
use rustc_target::spec::Target;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
};
|
||||
let bytes = CStr::from_ptr(fname_ptr).to_bytes();
|
||||
let os = OsStr::from_bytes(bytes);
|
||||
Ok(PathBuf::from(os))
|
||||
try_canonicalize(Path::new(os)).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
|
|
@ -122,7 +122,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
if (data_base..data_end).contains(&addr) {
|
||||
let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
|
||||
let os = OsStr::from_bytes(bytes);
|
||||
return Ok(PathBuf::from(os));
|
||||
return try_canonicalize(Path::new(os)).map_err(|e| e.to_string());
|
||||
}
|
||||
if (*current).ldinfo_next == 0 {
|
||||
break;
|
||||
|
|
@ -169,7 +169,12 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
|
||||
filename.truncate(n);
|
||||
|
||||
Ok(OsString::from_wide(&filename).into())
|
||||
let path = try_canonicalize(OsString::from_wide(&filename)).map_err(|e| e.to_string())?;
|
||||
|
||||
// See comments on this target function, but the gist is that
|
||||
// gcc chokes on verbatim paths which fs::canonicalize generates
|
||||
// so we try to avoid those kinds of paths.
|
||||
Ok(rustc_fs_util::fix_windows_verbatim_for_gcc(&path))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
|
|
@ -177,37 +182,13 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
Err("current_dll_path is not supported on WASI".to_string())
|
||||
}
|
||||
|
||||
pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
|
||||
let target = crate::config::host_tuple();
|
||||
let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()];
|
||||
let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string()));
|
||||
if let Ok(dll) = path {
|
||||
// use `parent` twice to chop off the file name and then also the
|
||||
// directory containing the dll which should be either `lib` or `bin`.
|
||||
if let Some(path) = dll.parent().and_then(|p| p.parent()) {
|
||||
// The original `path` pointed at the `rustc_driver` crate's dll.
|
||||
// Now that dll should only be in one of two locations. The first is
|
||||
// in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
|
||||
// other is the target's libdir, for example
|
||||
// `$sysroot/lib/rustlib/$target/lib/*.dll`.
|
||||
//
|
||||
// We don't know which, so let's assume that if our `path` above
|
||||
// ends in `$target` we *could* be in the target libdir, and always
|
||||
// assume that we may be in the main libdir.
|
||||
sysroot_candidates.push(path.to_owned());
|
||||
|
||||
if path.ends_with(target) {
|
||||
sysroot_candidates.extend(
|
||||
path.parent() // chop off `$target`
|
||||
.and_then(|p| p.parent()) // chop off `rustlib`
|
||||
.and_then(|p| p.parent()) // chop off `lib`
|
||||
.map(|s| s.to_owned()),
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn sysroot_with_fallback(sysroot: &Path) -> SmallVec<[PathBuf; 2]> {
|
||||
let mut candidates = smallvec![sysroot.to_owned()];
|
||||
let default_sysroot = get_or_default_sysroot();
|
||||
if default_sysroot != sysroot {
|
||||
candidates.push(default_sysroot);
|
||||
}
|
||||
|
||||
sysroot_candidates
|
||||
candidates
|
||||
}
|
||||
|
||||
/// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
|
||||
|
|
@ -219,17 +200,8 @@ pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
|
|||
/// This function checks if sysroot is found using env::args().next(), and if it
|
||||
/// is not found, finds sysroot from current rustc_driver dll.
|
||||
pub fn get_or_default_sysroot() -> PathBuf {
|
||||
// Follow symlinks. If the resolved path is relative, make it absolute.
|
||||
fn canonicalize(path: PathBuf) -> PathBuf {
|
||||
let path = try_canonicalize(&path).unwrap_or(path);
|
||||
// See comments on this target function, but the gist is that
|
||||
// gcc chokes on verbatim paths which fs::canonicalize generates
|
||||
// so we try to avoid those kinds of paths.
|
||||
fix_windows_verbatim_for_gcc(&path)
|
||||
}
|
||||
|
||||
fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
|
||||
let dll = current_dll_path().map(|s| canonicalize(s))?;
|
||||
let dll = current_dll_path()?;
|
||||
|
||||
// `dll` will be in one of the following two:
|
||||
// - compiler's libdir: $sysroot/lib/*.dll
|
||||
|
|
@ -242,7 +214,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
|
|||
dll.display()
|
||||
))?;
|
||||
|
||||
// if `dir` points target's dir, move up to the sysroot
|
||||
// if `dir` points to target's dir, move up to the sysroot
|
||||
let mut sysroot_dir = if dir.ends_with(crate::config::host_tuple()) {
|
||||
dir.parent() // chop off `$target`
|
||||
.and_then(|p| p.parent()) // chop off `rustlib`
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue