Merge pull request #2464 from rust-lang/rustc-pull

Rustc pull update
This commit is contained in:
Tshepang Mbambo 2025-06-12 13:30:15 +02:00 committed by GitHub
commit 7db4177547
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
498 changed files with 8922 additions and 5897 deletions

View file

@ -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:

View file

@ -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"

View file

@ -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;

View file

@ -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
}

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>;
}

View file

@ -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));
}
}

View file

@ -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:#?}"
);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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}

View file

@ -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);
}

View file

@ -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 {

View file

@ -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)]

View file

@ -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" }

View file

@ -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}

View file

@ -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(),

View file

@ -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"
}

View file

@ -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>(

View file

@ -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;

View file

@ -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)]

View file

@ -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"]

View file

@ -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,

View file

@ -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;

View file

@ -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)
}

View file

@ -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(..) => {}
}
}

View file

@ -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() {

View file

@ -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

View file

@ -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),

View file

@ -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
}
}
}

View file

@ -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)]

View file

@ -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

View file

@ -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());

View file

@ -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

View file

@ -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 =

View file

@ -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;
}

View file

@ -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)]

View file

@ -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)]

View file

@ -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]`.

View file

@ -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.
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!

View file

@ -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).

View file

@ -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

View file

@ -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)]

View file

@ -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"

View file

@ -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;
}

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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()

View file

@ -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),

View file

@ -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 {

View file

@ -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)
}
}

View file

@ -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 {

View file

@ -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)));

View file

@ -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) => {

View file

@ -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()
{

View file

@ -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

View file

@ -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:#?}"
);
}

View file

@ -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> {

View file

@ -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> {

View file

@ -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

View file

@ -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,

View file

@ -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);
});

View file

@ -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")
})

View file

@ -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);
}

View file

@ -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, \

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,
}

View file

@ -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 });
}
}
};

View file

@ -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)]

View file

@ -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,
}

View file

@ -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,

View file

@ -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) }
}

View file

@ -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(),

View file

@ -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()))
};

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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:?}"),
);
}
}

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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)
})

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -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));
}
}
_ => {}
}
}

View file

@ -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 {

View file

@ -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);

View file

@ -2,7 +2,6 @@
#![allow(internal_features)]
#![feature(assert_matches)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(min_specialization)]
// tidy-alphabetical-end

View file

@ -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