Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-04-26 04:59:48 +00:00
commit 6c2fa0bce7
221 changed files with 3217 additions and 2142 deletions

View file

@ -1927,7 +1927,7 @@ impl AttrArgs {
}
/// Delimited arguments, as used in `#[attr()/[]/{}]` or `mac!()/[]/{}`.
#[derive(Clone, Encodable, Decodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct DelimArgs {
pub dspan: DelimSpan,
pub delim: Delimiter, // Note: `Delimiter::Invisible` never occurs
@ -1942,18 +1942,6 @@ impl DelimArgs {
}
}
impl<CTX> HashStable<CTX> for DelimArgs
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
let DelimArgs { dspan, delim, tokens } = self;
dspan.hash_stable(ctx, hasher);
delim.hash_stable(ctx, hasher);
tokens.hash_stable(ctx, hasher);
}
}
/// Represents a macro definition.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MacroDef {

View file

@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
test(attr(deny(warnings)))
@ -14,7 +15,6 @@
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustdoc_internals)]

View file

@ -32,12 +32,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
@ -916,7 +916,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs {
DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() }
args.clone()
}
/// Lower an associated item constraint.

View file

@ -4,11 +4,11 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_is_partitioned)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -1,7 +1,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -3,7 +3,7 @@ use std::collections::BTreeMap;
use std::ops::Deref;
use std::sync::LazyLock;
use rustc_ast::{self as ast, DelimArgs};
use rustc_ast as ast;
use rustc_attr_data_structures::AttributeKind;
use rustc_errors::{DiagCtxtHandle, Diagnostic};
use rustc_feature::Features;
@ -315,11 +315,7 @@ impl<'sess> AttributeParser<'sess> {
fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
match args {
ast::AttrArgs::Empty => AttrArgs::Empty,
ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(DelimArgs {
dspan: args.dspan,
delim: args.delim,
tokens: args.tokens.clone(),
}),
ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).

View file

@ -77,8 +77,8 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -49,7 +49,7 @@ impl<'tcx> UniverseInfo<'tcx> {
UniverseInfo::RelateTys { expected, found }
}
pub(crate) fn report_error(
pub(crate) fn report_erroneous_element(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
@ -68,7 +68,7 @@ impl<'tcx> UniverseInfo<'tcx> {
mbcx.buffer_error(err);
}
UniverseInfo::TypeOp(ref type_op_info) => {
type_op_info.report_error(mbcx, placeholder, error_element, cause);
type_op_info.report_erroneous_element(mbcx, placeholder, error_element, cause);
}
UniverseInfo::Other => {
// FIXME: This error message isn't great, but it doesn't show
@ -145,8 +145,11 @@ pub(crate) trait TypeOpInfo<'tcx> {
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'infcx>>;
/// Constraints require that `error_element` appear in the
/// values of `placeholder`, but this cannot be proven to
/// hold. Report an error.
#[instrument(level = "debug", skip(self, mbcx))]
fn report_error(
fn report_erroneous_element(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
@ -190,12 +193,7 @@ pub(crate) trait TypeOpInfo<'tcx> {
let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
debug!(?nice_error);
if let Some(nice_error) = nice_error {
mbcx.buffer_error(nice_error);
} else {
mbcx.buffer_error(self.fallback_error(tcx, span));
}
mbcx.buffer_error(nice_error.unwrap_or_else(|| self.fallback_error(tcx, span)));
}
}
@ -450,7 +448,8 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
ty::ReVar(vid) => universe_of_region(vid),
_ => ty::UniverseIndex::ROOT,
};
let matches =
// Are the two regions the same?
let regions_the_same =
|a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
_ => a_region == b_region,
@ -459,7 +458,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
|constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint {
Constraint::RegSubReg(sub, sup)
if ((exact && sup == placeholder_region)
|| (!exact && matches(sup, placeholder_region)))
|| (!exact && regions_the_same(sup, placeholder_region)))
&& sup != sub =>
{
Some((sub, cause.clone()))
@ -468,23 +467,21 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
if (exact
&& sup == placeholder_region
&& !universe_of_region(vid).can_name(placeholder_universe))
|| (!exact && matches(sup, placeholder_region)) =>
|| (!exact && regions_the_same(sup, placeholder_region)) =>
{
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
}
_ => None,
};
let mut info = region_constraints
.constraints
.iter()
.find_map(|(constraint, cause)| check(constraint, cause, true));
if info.is_none() {
info = region_constraints
let mut find_culprit = |exact_match: bool| {
region_constraints
.constraints
.iter()
.find_map(|(constraint, cause)| check(constraint, cause, false));
}
let (sub_region, cause) = info?;
.find_map(|(constraint, cause)| check(constraint, cause, exact_match))
};
let (sub_region, cause) = find_culprit(true).or_else(|| find_culprit(false))?;
debug!(?sub_region, "cause = {:#?}", cause);
let error = match (error_region, sub_region.kind()) {

View file

@ -405,7 +405,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let universe = placeholder.universe;
let universe_info = self.regioncx.universe_info(universe);
universe_info.report_error(self, placeholder, error_element, cause);
universe_info.report_erroneous_element(self, placeholder, error_element, cause);
}
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {

View file

@ -2,12 +2,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View file

@ -1628,30 +1628,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
for error_element in self.scc_values.elements_contained_in(longer_fr_scc) {
match error_element {
RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {}
// If we have some bound universal region `'a`, then the only
// elements it can contain is itself -- we don't know anything
// else about it!
RegionElement::PlaceholderRegion(placeholder1) => {
if placeholder == placeholder1 {
continue;
}
}
}
// If we have some bound universal region `'a`, then the only
// elements it can contain is itself -- we don't know anything
// else about it!
if let Some(error_element) = self
.scc_values
.elements_contained_in(longer_fr_scc)
.find(|e| *e != RegionElement::PlaceholderRegion(placeholder))
{
// Stop after the first error, it gets too noisy otherwise, and does not provide more information.
errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
longer_fr,
error_element,
placeholder,
});
// Stop after the first error, it gets too noisy otherwise, and does not provide more
// information.
break;
} else {
debug!("check_bound_universal_region: all bounds satisfied");
}
debug!("check_bound_universal_region: all bounds satisfied");
}
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]
@ -2071,7 +2064,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
constraint.category
};
match category {
let interest = match category {
// Returns usually provide a type to blame and have specially written diagnostics,
// so prioritize them.
ConstraintCategory::Return(_) => 0,
@ -2123,9 +2116,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// specific, and are not used for relations that would make sense to blame.
ConstraintCategory::BoringNoLocation => 6,
// Do not blame internal constraints.
ConstraintCategory::Internal => 7,
ConstraintCategory::IllegalUniverse => 8,
}
ConstraintCategory::IllegalUniverse => 7,
ConstraintCategory::Internal => 8,
};
debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}");
interest
};
let best_choice = if blame_source {

View file

@ -21,7 +21,7 @@ rustc_index::newtype_index! {
/// An individual element in a region value -- the value of a
/// particular region variable consists of a set of these elements.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum RegionElement {
/// A point in the control-flow graph.
Location(Location),

View file

@ -5,6 +5,7 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@ -12,7 +13,6 @@
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_quote)]
#![feature(rustdoc_internals)]

View file

@ -41,8 +41,8 @@ use std::sync::Arc;
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, TargetConfig};
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
@ -178,7 +178,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
}
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
fn target_config(&self, sess: &Session) -> TargetConfig {
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
@ -197,7 +197,16 @@ impl CodegenBackend for CraneliftCodegenBackend {
};
// FIXME do `unstable_target_features` properly
let unstable_target_features = target_features.clone();
(target_features, unstable_target_features)
TargetConfig {
target_features,
unstable_target_features,
// Cranelift does not yet support f16 or f128
has_reliable_f16: false,
has_reliable_f16_math: false,
has_reliable_f128: false,
has_reliable_f128_math: false,
}
}
fn print_version(&self) {

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-04-17"
channel = "nightly-2025-04-25"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -165,10 +165,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
let mut input_registers = vec![];
for op in rust_operands {
if let InlineAsmOperandRef::In { reg, .. } = *op {
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
input_registers.push(reg_name);
}
if let InlineAsmOperandRef::In { reg, .. } = *op
&& let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg)
{
input_registers.push(reg_name);
}
}

View file

@ -33,12 +33,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
if value.get_type() == self.bool_type.make_pointer() {
if let Some(pointee) = typ.get_pointee() {
if pointee.dyncast_vector().is_some() {
panic!()
}
}
if value.get_type() == self.bool_type.make_pointer()
&& let Some(pointee) = typ.get_pointee()
&& pointee.dyncast_vector().is_some()
{
panic!()
}
// NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
// SIMD builtins require a constant value.

View file

@ -242,10 +242,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
let global = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
if let Some(global) = self.get_declared_value(sym) {
if self.val_ty(global) != self.type_ptr_to(gcc_type) {
span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
}
if let Some(global) = self.get_declared_value(sym)
&& self.val_ty(global) != self.type_ptr_to(gcc_type)
{
span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
}
let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);

View file

@ -126,14 +126,15 @@ fn make_mir_scope<'gcc, 'tcx>(
return;
};
if let Some(ref vars) = *variables {
if !vars.contains(scope) && scope_data.inlined.is_none() {
// Do not create a DIScope if there are no variables defined in this
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
debug_context.scopes[scope] = parent_scope;
instantiated.insert(scope);
return;
}
if let Some(ref vars) = *variables
&& !vars.contains(scope)
&& scope_data.inlined.is_none()
{
// Do not create a DIScope if there are no variables defined in this
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
debug_context.scopes[scope] = parent_scope;
instantiated.insert(scope);
return;
}
let loc = cx.lookup_debug_loc(scope_data.span.lo());

View file

@ -55,7 +55,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
)
} else if let Some(feature) = feature.strip_prefix('-') {
// FIXME: Why do we not remove implied features on "-" here?
// We do the equivalent above in `target_features_cfg`.
// We do the equivalent above in `target_config`.
// See <https://github.com/rust-lang/rust/issues/134792>.
all_rust_features.push((false, feature));
} else if !feature.is_empty() && diagnostics {
@ -136,14 +136,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
});
features.extend(feats);
if diagnostics {
if let Some(f) = check_tied_features(sess, &featsmap) {
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
features: f,
span: None,
missing_features: None,
});
}
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
features: f,
span: None,
missing_features: None,
});
}
features

View file

@ -22,7 +22,7 @@
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![deny(clippy::pattern_type_mismatch)]
#![allow(clippy::needless_lifetimes)]
#![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]
// Some "regular" crates we want to share with rustc
extern crate object;
@ -102,7 +102,7 @@ use rustc_codegen_ssa::back::write::{
};
use rustc_codegen_ssa::base::codegen_crate;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::DiagCtxtHandle;
@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
.join(sess)
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess, &self.target_info)
fn target_config(&self, sess: &Session) -> TargetConfig {
target_config(sess, &self.target_info)
}
}
@ -485,10 +485,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
}
/// Returns the features that should be set in `cfg(target_feature)`.
fn target_features_cfg(
sess: &Session,
target_info: &LockedTargetInfo,
) -> (Vec<Symbol>, Vec<Symbol>) {
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
// TODO(antoyo): use global_gcc_features.
let f = |allow_unstable| {
sess.target
@ -523,5 +520,14 @@ fn target_features_cfg(
let target_features = f(false);
let unstable_target_features = f(true);
(target_features, unstable_target_features)
TargetConfig {
target_features,
unstable_target_features,
// There are no known bugs with GCC support for f16 or f128
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
}
}

View file

@ -102,10 +102,10 @@ fn uncached_gcc_type<'gcc, 'tcx>(
let mut name = with_no_trimmed_paths!(layout.ty.to_string());
if let (&ty::Adt(def, _), &Variants::Single { index }) =
(layout.ty.kind(), &layout.variants)
&& def.is_enum()
&& !def.variants().is_empty()
{
if def.is_enum() && !def.variants().is_empty() {
write!(&mut name, "::{}", def.variant(index).name).unwrap();
}
write!(&mut name, "::{}", def.variant(index).name).unwrap();
}
if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
(layout.ty.kind(), &layout.variants)
@ -264,10 +264,10 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
}
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
if let BackendRepr::Scalar(ref scalar) = self.backend_repr {
if scalar.is_bool() {
return cx.type_i1();
}
if let BackendRepr::Scalar(ref scalar) = self.backend_repr
&& scalar.is_bool()
{
return cx.type_i1();
}
self.gcc_type(cx)
}

View file

@ -1,5 +1,7 @@
//! The common code for `tests/lang_tests_*.rs`
#![allow(clippy::uninlined_format_args)]
use std::env::{self, current_dir};
use std::path::{Path, PathBuf};
use std::process::Command;

View file

@ -5,6 +5,7 @@
// stdout: 10
// 10
// 42
// 1
#![feature(no_core)]
#![no_std]
@ -21,6 +22,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3
)
}
static mut ONE: usize = 1;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
@ -28,6 +31,10 @@ extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, d);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, j);
let ptr = ONE as *mut usize;
let value = ptr as usize;
libc::printf(b"%ld\n\0" as *const u8 as *const i8, value);
}
0
}

View file

@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@ -15,7 +16,6 @@
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
#![feature(slice_as_array)]
#![feature(try_blocks)]
@ -29,7 +29,7 @@ use back::owned_target_machine::OwnedTargetMachine;
use back::write::{create_informational_target_machine, create_target_machine};
use context::SimpleCx;
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
use llvm_util::target_features_cfg;
use llvm_util::target_config;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@ -37,7 +37,7 @@ use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagCtxtHandle, FatalError};
use rustc_metadata::EncodedMetadata;
@ -338,8 +338,8 @@ impl CodegenBackend for LlvmCodegenBackend {
llvm_util::print_version();
}
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess)
fn target_config(&self, sess: &Session) -> TargetConfig {
target_config(sess)
}
fn codegen_crate<'tcx>(

View file

@ -6,6 +6,7 @@ use std::sync::Once;
use std::{ptr, slice, str};
use libc::c_int;
use rustc_codegen_ssa::TargetConfig;
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -302,7 +303,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
/// Must express features in the way Rust understands them.
///
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
pub(crate) fn target_config(sess: &Session) -> TargetConfig {
// Add base features for the target.
// We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
// The reason is that if LLVM considers a feature implied but we do not, we don't want that to
@ -402,7 +403,89 @@ pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>)
let target_features = f(false);
let unstable_target_features = f(true);
(target_features, unstable_target_features)
let mut cfg = TargetConfig {
target_features,
unstable_target_features,
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
};
update_target_reliable_float_cfg(sess, &mut cfg);
cfg
}
/// Determine whether or not experimental float types are reliable based on known bugs.
fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
let target_arch = sess.target.arch.as_ref();
let target_os = sess.target.options.os.as_ref();
let target_env = sess.target.options.env.as_ref();
let target_abi = sess.target.options.abi.as_ref();
let target_pointer_width = sess.target.pointer_width;
cfg.has_reliable_f16 = match (target_arch, target_os) {
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
("s390x", _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
("csky", _) => false,
("hexagon", _) => false,
("powerpc" | "powerpc64", _) => false,
("sparc" | "sparc64", _) => false,
("wasm32" | "wasm64", _) => false,
// `f16` support only requires that symbols converting to and from `f32` are available. We
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
// do not have other ABI issues or LLVM crashes.
_ => true,
};
cfg.has_reliable_f128 = match (target_arch, target_os) {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
("mips64" | "mips64r6", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
("nvptx64", _) => false,
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
// list at <https://github.com/rust-lang/rust/issues/116909>)
("powerpc" | "powerpc64", _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
("sparc", _) => false,
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
// not fail if our compiler-builtins is linked.
("x86", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// There are no known problems on other platforms, so the only requirement is that symbols
// are available. `compiler-builtins` provides all symbols required for core `f128`
// support, so this should work for everything else.
_ => true,
};
cfg.has_reliable_f16_math = match (target_arch, target_os) {
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
("x86" | "x86_64", _) => false,
// Assume that working `f16` means working `f16` math for most platforms, since
// operations just go through `f32`.
_ => true,
} && cfg.has_reliable_f16;
cfg.has_reliable_f128_math = match (target_arch, target_os) {
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
// `long double` is not IEEE binary128. See
// <https://github.com/llvm/llvm-project/issues/44744>.
//
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
// (ld is 80-bit extended precision).
("x86_64", _) => false,
(_, "linux") if target_pointer_width == 64 => true,
_ => false,
} && cfg.has_reliable_f128;
}
pub(crate) fn print_version() {
@ -686,7 +769,7 @@ pub(crate) fn global_llvm_features(
)
} else if let Some(feature) = feature.strip_prefix('-') {
// FIXME: Why do we not remove implied features on "-" here?
// We do the equivalent above in `target_features_cfg`.
// We do the equivalent above in `target_config`.
// See <https://github.com/rust-lang/rust/issues/134792>.
all_rust_features.push((false, feature));
} else if !feature.is_empty() {

View file

@ -2,13 +2,13 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(rustdoc_internals)]
#![feature(string_from_utf8_lossy_owned)]
@ -235,6 +235,24 @@ pub struct CrateInfo {
pub lint_levels: CodegenLintLevels,
}
/// Target-specific options that get set in `cfg(...)`.
///
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
pub struct TargetConfig {
/// Options to be set in `cfg(target_features)`.
pub target_features: Vec<Symbol>,
/// Options to be set in `cfg(target_features)`, but including unstable features.
pub unstable_target_features: Vec<Symbol>,
/// Option for `cfg(target_has_reliable_f16)`, true if `f16` basic arithmetic works.
pub has_reliable_f16: bool,
/// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work.
pub has_reliable_f16_math: bool,
/// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works.
pub has_reliable_f128: bool,
/// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work.
pub has_reliable_f128_math: bool,
}
#[derive(Encodable, Decodable)]
pub struct CodegenResults {
pub modules: Vec<CompiledModule>,

View file

@ -18,7 +18,7 @@ use super::write::WriteBackendMethods;
use crate::back::archive::ArArchiveBuilderBuilder;
use crate::back::link::link_binary;
use crate::back::write::TargetMachineFactoryFn;
use crate::{CodegenResults, ModuleCodegen};
use crate::{CodegenResults, ModuleCodegen, TargetConfig};
pub trait BackendTypes {
type Value: CodegenObject;
@ -50,8 +50,15 @@ pub trait CodegenBackend {
/// - The second is like the first, but also includes unstable features.
///
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
fn target_features_cfg(&self, _sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
(vec![], vec![])
fn target_config(&self, _sess: &Session) -> TargetConfig {
TargetConfig {
target_features: vec![],
unstable_target_features: vec![],
has_reliable_f16: true,
has_reliable_f16_math: true,
has_reliable_f128: true,
has_reliable_f128_math: true,
}
}
fn print_passes(&self) {}

View file

@ -1,12 +1,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]
#![feature(slice_ptr_get)]

View file

@ -39,8 +39,15 @@ impls_dyn_send_neg!(
[std::io::StderrLock<'_>]
);
#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
#[cfg(any(
unix,
target_os = "hermit",
all(target_vendor = "fortanix", target_env = "sgx"),
target_os = "solid_asp3",
target_os = "wasi",
target_os = "xous"
))]
// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
impl !DynSend for std::env::VarsOs {}
macro_rules! already_send {
@ -106,8 +113,15 @@ impls_dyn_sync_neg!(
[std::sync::mpsc::Sender<T> where T]
);
#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
#[cfg(any(
unix,
target_os = "hermit",
all(target_vendor = "fortanix", target_env = "sgx"),
target_os = "solid_asp3",
target_os = "wasi",
target_os = "xous"
))]
// Consistent with `std`, `env_imp::Env` is `!Sync` in these platforms
impl !DynSync for std::env::VarsOs {}
macro_rules! already_sync {

View file

@ -7,10 +7,10 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(decl_macro)]
#![feature(let_chains)]
#![feature(panic_backtrace_config)]
#![feature(panic_update_hook)]
#![feature(result_flattening)]

View file

@ -7,6 +7,7 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
@ -17,7 +18,6 @@
#![feature(default_field_values)]
#![feature(error_reporter)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View file

@ -1,11 +1,11 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(array_windows)]
#![feature(associated_type_defaults)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(macro_metavar_expr)]
#![feature(map_try_insert)]
#![feature(proc_macro_diagnostic)]

View file

@ -40,6 +40,26 @@ const GATED_CFGS: &[GatedCfg] = &[
// this is consistent with naming of the compiler flag it's for
(sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
(sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
(
sym::target_has_reliable_f16,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f16_math,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f128,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
(
sym::target_has_reliable_f128_math,
sym::cfg_target_has_reliable_f16_f128,
Features::cfg_target_has_reliable_f16_f128,
),
];
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.

View file

@ -205,6 +205,8 @@ declare_features! (
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
(internal, cfg_emscripten_wasm_eh, "1.86.0", None),
/// Allows checking whether or not the backend correctly supports unstable float types.
(internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows writing custom MIR

View file

@ -4,12 +4,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(closure_track_caller)]
#![feature(debug_closure_helpers)]
#![feature(exhaustive_patterns)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View file

@ -59,6 +59,7 @@ This API is completely unstable and subject to change.
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@ -67,7 +68,6 @@ This API is completely unstable and subject to change.
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]
#![feature(slice_partition_dedup)]

View file

@ -2,7 +2,7 @@
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
// tidy-alphabetical-start
#![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![recursion_limit = "256"]
// tidy-alphabetical-end

View file

@ -501,12 +501,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
.must_apply_modulo_regions()
{
label = false;
err.span_suggestion(
self.span,
"consider using the `From` trait instead",
format!("{}::from({})", self.cast_ty, snippet),
Applicability::MaybeIncorrect,
);
if let ty::Adt(def, args) = self.cast_ty.kind() {
err.span_suggestion_verbose(
self.span,
"consider using the `From` trait instead",
format!(
"{}::from({})",
fcx.tcx.value_path_str_with_args(def.did(), args),
snippet
),
Applicability::MaybeIncorrect,
);
} else {
err.span_suggestion(
self.span,
"consider using the `From` trait instead",
format!("{}::from({})", self.cast_ty, snippet),
Applicability::MaybeIncorrect,
);
};
}
}

View file

@ -1,11 +1,11 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(try_blocks)]
// tidy-alphabetical-end

View file

@ -16,12 +16,12 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(extend_one)]
#![feature(iterator_try_collect)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
#![recursion_limit = "512"] // For rustdoc
// tidy-alphabetical-end

View file

@ -1,8 +1,8 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(decl_macro)]
#![feature(file_buffered)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(try_blocks)]
// tidy-alphabetical-end

View file

@ -38,14 +38,25 @@ pub(crate) fn add_configuration(
codegen_backend: &dyn CodegenBackend,
) {
let tf = sym::target_feature;
let tf_cfg = codegen_backend.target_config(sess);
let (target_features, unstable_target_features) = codegen_backend.target_features_cfg(sess);
sess.unstable_target_features.extend(tf_cfg.unstable_target_features.iter().copied());
sess.target_features.extend(tf_cfg.target_features.iter().copied());
sess.unstable_target_features.extend(unstable_target_features.iter().copied());
cfg.extend(tf_cfg.target_features.into_iter().map(|feat| (tf, Some(feat))));
sess.target_features.extend(target_features.iter().copied());
cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
if tf_cfg.has_reliable_f16 {
cfg.insert((sym::target_has_reliable_f16, None));
}
if tf_cfg.has_reliable_f16_math {
cfg.insert((sym::target_has_reliable_f16_math, None));
}
if tf_cfg.has_reliable_f128 {
cfg.insert((sym::target_has_reliable_f128, None));
}
if tf_cfg.has_reliable_f128_math {
cfg.insert((sym::target_has_reliable_f128_math, None));
}
if sess.crt_static(None) {
cfg.insert((tf, Some(sym::crt_dash_static)));

View file

@ -21,6 +21,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
@ -28,7 +29,6 @@
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_order_by)]
#![feature(let_chains)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(try_blocks)]

View file

@ -1,7 +1,7 @@
// tidy-alphabetical-start
#![allow(rustc::default_hash_types)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_span)]

View file

@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(coroutines)]
@ -8,7 +9,6 @@
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]
#![feature(let_chains)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
#![feature(never_type)]

View file

@ -29,6 +29,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::potential_query_instability)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
@ -48,7 +49,6 @@
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(iter_from_coroutine)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]

View file

@ -121,11 +121,10 @@ impl<'tcx> Predicate<'tcx> {
/// unsoundly accept some programs. See #91068.
#[inline]
pub fn allow_normalization(self) -> bool {
// Keep this in sync with the one in `rustc_type_ir::inherent`!
match self.kind().skip_binder() {
PredicateKind::Clause(ClauseKind::WellFormed(_))
| PredicateKind::AliasRelate(..)
| PredicateKind::NormalizesTo(..) => false,
PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => {
false
}
PredicateKind::Clause(ClauseKind::Trait(_))
| PredicateKind::Clause(ClauseKind::HostEffect(..))
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
@ -137,6 +136,7 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Coerce(_)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
| PredicateKind::ConstEquate(_, _)
| PredicateKind::NormalizesTo(..)
| PredicateKind::Ambiguous => true,
}
}

View file

@ -3,10 +3,10 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(try_blocks)]
// tidy-alphabetical-end

View file

@ -1,10 +1,10 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(assert_matches)]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
#![feature(file_buffered)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(try_blocks)]
// tidy-alphabetical-end

View file

@ -87,11 +87,8 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
&& let Some((func_def_id, _)) = func.const_fn_def()
&& self.tcx.is_intrinsic(func_def_id, sym::transmute)
&& let span = self.body.source_info(location).span
&& let Some(lint) = self.is_unnecessary_transmute(
func,
self.tcx.sess.source_map().span_to_snippet(arg).expect("ok"),
span,
)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(arg)
&& let Some(lint) = self.is_unnecessary_transmute(func, snippet, span)
&& let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes)
{
self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint);

View file

@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(box_patterns)]
@ -7,7 +8,6 @@
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(let_chains)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]

View file

@ -1,9 +1,9 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(array_windows)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(let_chains)]
// tidy-alphabetical-end
use rustc_hir::lang_items::LangItem;

View file

@ -9,7 +9,6 @@ derive-where = "1.2.7"
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
tracing = "0.1"
@ -20,7 +19,6 @@ default = ["nightly"]
nightly = [
"dep:rustc_data_structures",
"dep:rustc_macros",
"dep:rustc_serialize",
"rustc_index/nightly",
"rustc_type_ir/nightly",
]

View file

@ -16,6 +16,7 @@
//! relate them structurally.
use rustc_type_ir::inherent::*;
use rustc_type_ir::solve::GoalSource;
use rustc_type_ir::{self as ty, Interner};
use tracing::{instrument, trace};
@ -49,7 +50,10 @@ where
// Structurally normalize the lhs.
let lhs = if let Some(alias) = lhs.to_alias_term() {
let term = self.next_term_infer_of_kind(lhs);
self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
self.add_goal(
GoalSource::TypeRelating,
goal.with(cx, ty::NormalizesTo { alias, term }),
);
term
} else {
lhs
@ -58,7 +62,10 @@ where
// Structurally normalize the rhs.
let rhs = if let Some(alias) = rhs.to_alias_term() {
let term = self.next_term_infer_of_kind(rhs);
self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term }));
self.add_goal(
GoalSource::TypeRelating,
goal.with(cx, ty::NormalizesTo { alias, term }),
);
term
} else {
rhs

View file

@ -22,7 +22,7 @@ use tracing::{debug, instrument, trace};
use crate::canonicalizer::Canonicalizer;
use crate::delegate::SolverDelegate;
use crate::resolve::EagerResolver;
use crate::solve::eval_ctxt::{CurrentGoalKind, NestedGoals};
use crate::solve::eval_ctxt::CurrentGoalKind;
use crate::solve::{
CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal,
MaybeCause, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput,
@ -112,13 +112,9 @@ where
// by `try_evaluate_added_goals()`.
let (certainty, normalization_nested_goals) = match self.current_goal_kind {
CurrentGoalKind::NormalizesTo => {
let NestedGoals { normalizes_to_goals, goals } =
std::mem::take(&mut self.nested_goals);
if cfg!(debug_assertions) {
assert!(normalizes_to_goals.is_empty());
if goals.is_empty() {
assert!(matches!(goals_certainty, Certainty::Yes));
}
let goals = std::mem::take(&mut self.nested_goals);
if goals.is_empty() {
assert!(matches!(goals_certainty, Certainty::Yes));
}
(certainty, NestedNormalizationGoals(goals))
}

View file

@ -1,8 +1,8 @@
use std::mem;
use std::ops::ControlFlow;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_macros::HashStable_NoContext;
use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
@ -14,7 +14,6 @@ use rustc_type_ir::{
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
TypingMode,
};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use tracing::{instrument, trace};
use crate::coherence;
@ -114,7 +113,7 @@ where
pub(super) search_graph: &'a mut SearchGraph<D>,
nested_goals: NestedGoals<I>,
nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
pub(super) origin_span: I::Span,
@ -129,38 +128,6 @@ where
pub(super) inspect: ProofTreeBuilder<D>,
}
#[derive_where(Clone, Debug, Default; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
)]
struct NestedGoals<I: Interner> {
/// These normalizes-to goals are treated specially during the evaluation
/// loop. In each iteration we take the RHS of the projection, replace it with
/// a fresh inference variable, and only after evaluating that goal do we
/// equate the fresh inference variable with the actual RHS of the predicate.
///
/// This is both to improve caching, and to avoid using the RHS of the
/// projection predicate to influence the normalizes-to candidate we select.
///
/// Forgetting to replace the RHS with a fresh inference variable when we evaluate
/// this goal results in an ICE..
pub normalizes_to_goals: Vec<Goal<I, ty::NormalizesTo<I>>>,
/// The rest of the goals which have not yet processed or remain ambiguous.
pub goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
}
impl<I: Interner> NestedGoals<I> {
fn new() -> Self {
Self { normalizes_to_goals: Vec::new(), goals: Vec::new() }
}
fn is_empty(&self) -> bool {
self.normalizes_to_goals.is_empty() && self.goals.is_empty()
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum GenerateProofTree {
@ -332,7 +299,7 @@ where
let mut ecx = EvalCtxt {
delegate,
search_graph: &mut search_graph,
nested_goals: NestedGoals::new(),
nested_goals: Default::default(),
inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree),
// Only relevant when canonicalizing the response,
@ -385,7 +352,7 @@ where
predefined_opaques_in_body: input.predefined_opaques_in_body,
max_input_universe: canonical_input.canonical.max_universe,
search_graph,
nested_goals: NestedGoals::new(),
nested_goals: Default::default(),
origin_span: I::Span::dummy(),
tainted: Ok(()),
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
@ -629,78 +596,83 @@ where
/// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
let cx = self.cx();
let mut goals = core::mem::take(&mut self.nested_goals);
// If this loop did not result in any progress, what's our final certainty.
let mut unchanged_certainty = Some(Certainty::Yes);
for goal in goals.normalizes_to_goals {
// Replace the goal with an unconstrained infer var, so the
// RHS does not affect projection candidate assembly.
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
let unconstrained_goal = goal.with(
cx,
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
);
let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
GoalEvaluationKind::Nested,
GoalSource::TypeRelating,
unconstrained_goal,
)?;
// Add the nested goals from normalization to our own nested goals.
trace!(?nested_goals);
goals.goals.extend(nested_goals);
// Finally, equate the goal's RHS with the unconstrained var.
for (source, goal) in mem::take(&mut self.nested_goals) {
// We treat normalizes-to goals specially here. In each iteration we take the
// RHS of the projection, replace it with a fresh inference variable, and only
// after evaluating that goal do we equate the fresh inference variable with the
// actual RHS of the predicate.
//
// SUBTLE:
// We structurally relate aliases here. This is necessary
// as we otherwise emit a nested `AliasRelate` goal in case the
// returned term is a rigid alias, resulting in overflow.
// This is both to improve caching, and to avoid using the RHS of the
// projection predicate to influence the normalizes-to candidate we select.
//
// It is correct as both `goal.predicate.term` and `unconstrained_rhs`
// start out as an unconstrained inference variable so any aliases get
// fully normalized when instantiating it.
//
// FIXME: Strictly speaking this may be incomplete if the normalized-to
// type contains an ambiguous alias referencing bound regions. We should
// consider changing this to only use "shallow structural equality".
self.eq_structurally_relating_aliases(
goal.param_env,
goal.predicate.term,
unconstrained_rhs,
)?;
// Forgetting to replace the RHS with a fresh inference variable when we evaluate
// this goal results in an ICE.
if let Some(pred) = goal.predicate.as_normalizes_to() {
// We should never encounter higher-ranked normalizes-to goals.
let pred = pred.no_bound_vars().unwrap();
// Replace the goal with an unconstrained infer var, so the
// RHS does not affect projection candidate assembly.
let unconstrained_rhs = self.next_term_infer_of_kind(pred.term);
let unconstrained_goal =
goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
// We only look at the `projection_ty` part here rather than
// looking at the "has changed" return from evaluate_goal,
// because we expect the `unconstrained_rhs` part of the predicate
// to have changed -- that means we actually normalized successfully!
let with_resolved_vars = self.resolve_vars_if_possible(goal);
if goal.predicate.alias != with_resolved_vars.predicate.alias {
unchanged_certainty = None;
}
let (NestedNormalizationGoals(nested_goals), _, certainty) =
self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?;
// Add the nested goals from normalization to our own nested goals.
trace!(?nested_goals);
self.nested_goals.extend(nested_goals);
match certainty {
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.normalizes_to_goals.push(with_resolved_vars);
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
// Finally, equate the goal's RHS with the unconstrained var.
//
// SUBTLE:
// We structurally relate aliases here. This is necessary
// as we otherwise emit a nested `AliasRelate` goal in case the
// returned term is a rigid alias, resulting in overflow.
//
// It is correct as both `goal.predicate.term` and `unconstrained_rhs`
// start out as an unconstrained inference variable so any aliases get
// fully normalized when instantiating it.
//
// FIXME: Strictly speaking this may be incomplete if the normalized-to
// type contains an ambiguous alias referencing bound regions. We should
// consider changing this to only use "shallow structural equality".
self.eq_structurally_relating_aliases(
goal.param_env,
pred.term,
unconstrained_rhs,
)?;
// We only look at the `projection_ty` part here rather than
// looking at the "has changed" return from evaluate_goal,
// because we expect the `unconstrained_rhs` part of the predicate
// to have changed -- that means we actually normalized successfully!
let with_resolved_vars = self.resolve_vars_if_possible(goal);
if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias {
unchanged_certainty = None;
}
}
}
for (source, goal) in goals.goals {
let (has_changed, certainty) =
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
if has_changed == HasChanged::Yes {
unchanged_certainty = None;
}
match certainty {
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.push((source, with_resolved_vars));
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
}
}
} else {
let (has_changed, certainty) =
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
if has_changed == HasChanged::Yes {
unchanged_certainty = None;
}
match certainty {
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.goals.push((source, goal));
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
match certainty {
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.push((source, goal));
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
}
}
}
}
@ -717,23 +689,12 @@ where
self.delegate.cx()
}
#[instrument(level = "trace", skip(self))]
pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<I, ty::NormalizesTo<I>>) {
goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(
self,
GoalSource::TypeRelating,
goal.param_env,
));
self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
self.nested_goals.normalizes_to_goals.push(goal);
}
#[instrument(level = "debug", skip(self))]
pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
goal.predicate =
goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
self.nested_goals.goals.push((source, goal));
self.nested_goals.push((source, goal));
}
#[instrument(level = "trace", skip(self, goals))]

View file

@ -412,20 +412,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
}
}
pub(crate) fn add_normalizes_to_goal(
&mut self,
delegate: &D,
max_input_universe: ty::UniverseIndex,
goal: Goal<I, ty::NormalizesTo<I>>,
) {
self.add_goal(
delegate,
max_input_universe,
GoalSource::TypeRelating,
goal.with(delegate.cx(), goal.predicate),
);
}
pub(crate) fn add_goal(
&mut self,
delegate: &D,

View file

@ -4,13 +4,13 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(debug_closure_helpers)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(string_from_utf8_lossy_owned)]
// tidy-alphabetical-end

View file

@ -683,10 +683,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
if !other_attr.has_any_name(ALLOW_LIST) {
let path = other_attr.path();
let path: Vec<_> = path.iter().map(|s| s.as_str()).collect();
let other_attr_name = path.join("::");
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
span: other_attr.span(),
naked_span: attr.span(),
attr: other_attr.name().unwrap(),
attr: other_attr_name,
});
return;

View file

@ -1249,7 +1249,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
pub span: Span,
#[label(passes_naked_attribute)]
pub naked_span: Span,
pub attr: Symbol,
pub attr: String,
}
#[derive(Diagnostic)]

View file

@ -6,9 +6,9 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(let_chains)]
#![feature(map_try_insert)]
#![feature(rustdoc_internals)]
#![feature(try_blocks)]

View file

@ -6,7 +6,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![allow(unused_crate_dependencies)]
#![cfg_attr(feature = "rustc", feature(let_chains))]
#![cfg_attr(all(feature = "rustc", bootstrap), feature(let_chains))]
// tidy-alphabetical-end
pub mod constructor;

View file

@ -1,9 +1,9 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(associated_type_defaults)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
#![feature(try_blocks)]
// tidy-alphabetical-end

View file

@ -46,6 +46,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::unhash::UnhashMap;
use rustc_index::{Idx, IndexVec};
use rustc_serialize::opaque::mem_encoder::MemEncoder;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use tracing::{debug, instrument};
@ -105,22 +106,12 @@ impl SerializedDepGraph {
) -> impl Iterator<Item = SerializedDepNodeIndex> + Clone {
let header = self.edge_list_indices[source];
let mut raw = &self.edge_list_data[header.start()..];
// Figure out where the edge list for `source` ends by getting the start index of the next
// edge list, or the end of the array if this is the last edge.
let end = self
.edge_list_indices
.get(source + 1)
.map(|h| h.start())
.unwrap_or_else(|| self.edge_list_data.len() - DEP_NODE_PAD);
// The number of edges for this node is implicitly stored in the combination of the byte
// width and the length.
let bytes_per_index = header.bytes_per_index();
let len = (end - header.start()) / bytes_per_index;
// LLVM doesn't hoist EdgeHeader::mask so we do it ourselves.
let mask = header.mask();
(0..len).map(move |_| {
(0..header.num_edges).map(move |_| {
// Doing this slicing in this order ensures that the first bounds check suffices for
// all the others.
let index = &raw[..DEP_NODE_SIZE];
@ -163,6 +154,7 @@ impl SerializedDepGraph {
#[derive(Debug, Clone, Copy)]
struct EdgeHeader {
repr: usize,
num_edges: u32,
}
impl EdgeHeader {
@ -205,9 +197,14 @@ impl SerializedDepGraph {
let graph_bytes = d.len() - (2 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position();
let mut nodes = IndexVec::with_capacity(node_count);
let mut fingerprints = IndexVec::with_capacity(node_count);
let mut edge_list_indices = IndexVec::with_capacity(node_count);
let mut nodes = IndexVec::from_elem_n(
DepNode { kind: D::DEP_KIND_NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) },
node_count,
);
let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_count);
let mut edge_list_indices =
IndexVec::from_elem_n(EdgeHeader { repr: 0, num_edges: 0 }, node_count);
// This estimation assumes that all of the encoded bytes are for the edge lists or for the
// fixed-size node headers. But that's not necessarily true; if any edge list has a length
// that spills out of the size we can bit-pack into SerializedNodeHeader then some of the
@ -226,11 +223,14 @@ impl SerializedDepGraph {
let node_header =
SerializedNodeHeader::<D> { bytes: d.read_array(), _marker: PhantomData };
let _i: SerializedDepNodeIndex = nodes.push(node_header.node());
debug_assert_eq!(_i.index(), _index);
let index = node_header.index();
let _i: SerializedDepNodeIndex = fingerprints.push(node_header.fingerprint());
debug_assert_eq!(_i.index(), _index);
let node = &mut nodes[index];
// Make sure there's no duplicate indices in the dep graph.
assert!(node_header.node().kind != D::DEP_KIND_NULL && node.kind == D::DEP_KIND_NULL);
*node = node_header.node();
fingerprints[index] = node_header.fingerprint();
// If the length of this node's edge list is small, the length is stored in the header.
// If it is not, we fall back to another decoder call.
@ -242,12 +242,11 @@ impl SerializedDepGraph {
let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize);
// The in-memory structure for the edges list stores the byte width of the edges on
// this node with the offset into the global edge data array.
let edges_header = node_header.edges_header(&edge_list_data);
let edges_header = node_header.edges_header(&edge_list_data, num_edges);
edge_list_data.extend(d.read_raw_bytes(edges_len_bytes));
let _i: SerializedDepNodeIndex = edge_list_indices.push(edges_header);
debug_assert_eq!(_i.index(), _index);
edge_list_indices[index] = edges_header;
}
// When we access the edge list data, we do a fixed-size read from the edge list data then
@ -298,9 +297,10 @@ impl SerializedDepGraph {
/// * In whatever bits remain, the length of the edge list for this node, if it fits
struct SerializedNodeHeader<D> {
// 2 bytes for the DepNode
// 4 bytes for the index
// 16 for Fingerprint in DepNode
// 16 for Fingerprint in NodeInfo
bytes: [u8; 34],
bytes: [u8; 38],
_marker: PhantomData<D>,
}
@ -310,6 +310,7 @@ struct Unpacked {
len: Option<u32>,
bytes_per_index: usize,
kind: DepKind,
index: SerializedDepNodeIndex,
hash: PackedFingerprint,
fingerprint: Fingerprint,
}
@ -331,6 +332,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
#[inline]
fn new(
node: DepNode,
index: DepNodeIndex,
fingerprint: Fingerprint,
edge_max_index: u32,
edge_count: usize,
@ -352,10 +354,11 @@ impl<D: Deps> SerializedNodeHeader<D> {
let hash: Fingerprint = node.hash.into();
// Using half-open ranges ensures an unconditional panic if we get the magic numbers wrong.
let mut bytes = [0u8; 34];
let mut bytes = [0u8; 38];
bytes[..2].copy_from_slice(&head.to_le_bytes());
bytes[2..18].copy_from_slice(&hash.to_le_bytes());
bytes[18..].copy_from_slice(&fingerprint.to_le_bytes());
bytes[2..6].copy_from_slice(&index.as_u32().to_le_bytes());
bytes[6..22].copy_from_slice(&hash.to_le_bytes());
bytes[22..].copy_from_slice(&fingerprint.to_le_bytes());
#[cfg(debug_assertions)]
{
@ -372,8 +375,9 @@ impl<D: Deps> SerializedNodeHeader<D> {
#[inline]
fn unpack(&self) -> Unpacked {
let head = u16::from_le_bytes(self.bytes[..2].try_into().unwrap());
let hash = self.bytes[2..18].try_into().unwrap();
let fingerprint = self.bytes[18..].try_into().unwrap();
let index = u32::from_le_bytes(self.bytes[2..6].try_into().unwrap());
let hash = self.bytes[6..22].try_into().unwrap();
let fingerprint = self.bytes[22..].try_into().unwrap();
let kind = head & mask(Self::KIND_BITS) as u16;
let bytes_per_index = (head >> Self::KIND_BITS) & mask(Self::WIDTH_BITS) as u16;
@ -383,6 +387,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
len: len.checked_sub(1),
bytes_per_index: bytes_per_index as usize + 1,
kind: DepKind::new(kind),
index: SerializedDepNodeIndex::from_u32(index),
hash: Fingerprint::from_le_bytes(hash).into(),
fingerprint: Fingerprint::from_le_bytes(fingerprint),
}
@ -398,6 +403,11 @@ impl<D: Deps> SerializedNodeHeader<D> {
self.unpack().bytes_per_index
}
#[inline]
fn index(&self) -> SerializedDepNodeIndex {
self.unpack().index
}
#[inline]
fn fingerprint(&self) -> Fingerprint {
self.unpack().fingerprint
@ -410,9 +420,10 @@ impl<D: Deps> SerializedNodeHeader<D> {
}
#[inline]
fn edges_header(&self, edge_list_data: &[u8]) -> EdgeHeader {
fn edges_header(&self, edge_list_data: &[u8], num_edges: u32) -> EdgeHeader {
EdgeHeader {
repr: (edge_list_data.len() << DEP_NODE_WIDTH_BITS) | (self.bytes_per_index() - 1),
num_edges,
}
}
}
@ -425,10 +436,15 @@ struct NodeInfo {
}
impl NodeInfo {
fn encode<D: Deps>(&self, e: &mut FileEncoder) {
fn encode<D: Deps>(&self, e: &mut MemEncoder, index: DepNodeIndex) {
let NodeInfo { node, fingerprint, ref edges } = *self;
let header =
SerializedNodeHeader::<D>::new(node, fingerprint, edges.max_index(), edges.len());
let header = SerializedNodeHeader::<D>::new(
node,
index,
fingerprint,
edges.max_index(),
edges.len(),
);
e.write_array(header.bytes);
if header.len().is_none() {
@ -450,8 +466,9 @@ impl NodeInfo {
/// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`.
#[inline]
fn encode_promoted<D: Deps>(
e: &mut FileEncoder,
e: &mut MemEncoder,
node: DepNode,
index: DepNodeIndex,
fingerprint: Fingerprint,
prev_index: SerializedDepNodeIndex,
colors: &DepNodeColorMap,
@ -464,7 +481,7 @@ impl NodeInfo {
let edge_max =
edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count);
let header = SerializedNodeHeader::<D>::new(node, index, fingerprint, edge_max, edge_count);
e.write_array(header.bytes);
if header.len().is_none() {
@ -498,6 +515,8 @@ struct EncoderState<D: Deps> {
total_edge_count: usize,
stats: Option<FxHashMap<DepKind, Stat>>,
mem_encoder: MemEncoder,
/// Stores the number of times we've encoded each dep kind.
kind_stats: Vec<u32>,
marker: PhantomData<D>,
@ -511,22 +530,28 @@ impl<D: Deps> EncoderState<D> {
total_edge_count: 0,
total_node_count: 0,
stats: record_stats.then(FxHashMap::default),
mem_encoder: MemEncoder::new(),
kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(),
marker: PhantomData,
}
}
#[inline]
fn alloc_index(&mut self) -> DepNodeIndex {
let index = DepNodeIndex::new(self.total_node_count);
self.total_node_count += 1;
index
}
#[inline]
fn record(
&mut self,
node: DepNode,
index: DepNodeIndex,
edge_count: usize,
edges: impl FnOnce(&mut Self) -> Vec<DepNodeIndex>,
record_graph: &Option<Lock<DepGraphQuery>>,
) -> DepNodeIndex {
let index = DepNodeIndex::new(self.total_node_count);
self.total_node_count += 1;
self.kind_stats[node.kind.as_usize()] += 1;
self.total_edge_count += edge_count;
@ -558,14 +583,25 @@ impl<D: Deps> EncoderState<D> {
index
}
#[inline]
fn flush_mem_encoder(&mut self) {
let data = &mut self.mem_encoder.data;
if data.len() > 64 * 1024 {
self.encoder.emit_raw_bytes(&data[..]);
data.clear();
}
}
/// Encodes a node to the current graph.
fn encode_node(
&mut self,
node: &NodeInfo,
record_graph: &Option<Lock<DepGraphQuery>>,
) -> DepNodeIndex {
node.encode::<D>(&mut self.encoder);
self.record(node.node, node.edges.len(), |_| node.edges[..].to_vec(), record_graph)
let index = self.alloc_index();
node.encode::<D>(&mut self.mem_encoder, index);
self.flush_mem_encoder();
self.record(node.node, index, node.edges.len(), |_| node.edges[..].to_vec(), record_graph)
}
/// Encodes a node that was promoted from the previous graph. It reads the information directly from
@ -581,20 +617,22 @@ impl<D: Deps> EncoderState<D> {
record_graph: &Option<Lock<DepGraphQuery>>,
colors: &DepNodeColorMap,
) -> DepNodeIndex {
let index = self.alloc_index();
let node = self.previous.index_to_node(prev_index);
let fingerprint = self.previous.fingerprint_by_index(prev_index);
let edge_count = NodeInfo::encode_promoted::<D>(
&mut self.encoder,
&mut self.mem_encoder,
node,
index,
fingerprint,
prev_index,
colors,
&self.previous,
);
self.flush_mem_encoder();
self.record(
node,
index,
edge_count,
|this| {
this.previous
@ -603,12 +641,14 @@ impl<D: Deps> EncoderState<D> {
.collect()
},
record_graph,
)
);
index
}
fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
let Self {
mut encoder,
mem_encoder,
total_node_count,
total_edge_count,
stats: _,
@ -617,6 +657,8 @@ impl<D: Deps> EncoderState<D> {
previous,
} = self;
encoder.emit_raw_bytes(&mem_encoder.data);
let node_count = total_node_count.try_into().unwrap();
let edge_count = total_edge_count.try_into().unwrap();

View file

@ -1,9 +1,9 @@
// tidy-alphabetical-start
#![allow(rustc::potential_query_instability, internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(assert_matches)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(let_chains)]
#![feature(min_specialization)]
// tidy-alphabetical-end

View file

@ -10,13 +10,13 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -4,7 +4,7 @@
//! compiler.
// tidy-alphabetical-start
#![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_chains))]
// tidy-alphabetical-end
pub mod cfi;

View file

@ -10,6 +10,8 @@ use crate::int_overflow::DebugStrictAdd;
use crate::leb128;
use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
pub mod mem_encoder;
// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------

View file

@ -0,0 +1,128 @@
use super::IntEncodedWithFixedSize;
use crate::{Encodable, Encoder, leb128};
pub struct MemEncoder {
pub data: Vec<u8>,
}
impl MemEncoder {
pub fn new() -> MemEncoder {
MemEncoder { data: vec![] }
}
#[inline]
pub fn position(&self) -> usize {
self.data.len()
}
pub fn finish(self) -> Vec<u8> {
self.data
}
/// Write up to `N` bytes to this encoder.
///
/// This function can be used to avoid the overhead of calling memcpy for writes that
/// have runtime-variable length, but are small and have a small fixed upper bound.
///
/// This can be used to do in-place encoding as is done for leb128 (without this function
/// we would need to write to a temporary buffer then memcpy into the encoder), and it can
/// also be used to implement the varint scheme we use for rmeta and dep graph encoding,
/// where we only want to encode the first few bytes of an integer. Note that common
/// architectures support fixed-size writes up to 8 bytes with one instruction, so while this
/// does in some sense do wasted work, we come out ahead.
#[inline]
pub fn write_with<const N: usize>(&mut self, visitor: impl FnOnce(&mut [u8; N]) -> usize) {
self.data.reserve(N);
let old_len = self.data.len();
// SAFETY: The above `reserve` ensures that there is enough
// room to write the encoded value to the vector's internal buffer.
// The memory is also initialized as 0.
let buf = unsafe {
let buf = self.data.as_mut_ptr().add(old_len) as *mut [u8; N];
*buf = [0; N];
&mut *buf
};
let written = visitor(buf);
if written > N {
Self::panic_invalid_write::<N>(written);
}
unsafe { self.data.set_len(old_len + written) };
}
#[cold]
#[inline(never)]
fn panic_invalid_write<const N: usize>(written: usize) {
panic!("MemEncoder::write_with::<{N}> cannot be used to write {written} bytes");
}
/// Helper for calls where [`MemEncoder::write_with`] always writes the whole array.
#[inline]
pub fn write_array<const N: usize>(&mut self, buf: [u8; N]) {
self.write_with(|dest| {
*dest = buf;
N
})
}
}
macro_rules! write_leb128 {
($this_fn:ident, $int_ty:ty, $write_leb_fn:ident) => {
#[inline]
fn $this_fn(&mut self, v: $int_ty) {
self.write_with(|buf| leb128::$write_leb_fn(buf, v))
}
};
}
impl Encoder for MemEncoder {
write_leb128!(emit_usize, usize, write_usize_leb128);
write_leb128!(emit_u128, u128, write_u128_leb128);
write_leb128!(emit_u64, u64, write_u64_leb128);
write_leb128!(emit_u32, u32, write_u32_leb128);
#[inline]
fn emit_u16(&mut self, v: u16) {
self.write_array(v.to_le_bytes());
}
#[inline]
fn emit_u8(&mut self, v: u8) {
self.write_array([v]);
}
write_leb128!(emit_isize, isize, write_isize_leb128);
write_leb128!(emit_i128, i128, write_i128_leb128);
write_leb128!(emit_i64, i64, write_i64_leb128);
write_leb128!(emit_i32, i32, write_i32_leb128);
#[inline]
fn emit_i16(&mut self, v: i16) {
self.write_array(v.to_le_bytes());
}
#[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s);
}
}
// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
// since the default implementations call `encode` on their slices internally.
impl Encodable<MemEncoder> for [u8] {
fn encode(&self, e: &mut MemEncoder) {
Encoder::emit_usize(e, self.len());
e.emit_raw_bytes(self);
}
}
impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut MemEncoder) {
let start_pos = e.position();
e.write_array(self.0.to_le_bytes());
let end_pos = e.position();
debug_assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
}
}

View file

@ -142,6 +142,10 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
| (sym::target_has_atomic, Some(_))
| (sym::target_has_atomic_equal_alignment, Some(_))
| (sym::target_has_atomic_load_store, Some(_))
| (sym::target_has_reliable_f16, None | Some(_))
| (sym::target_has_reliable_f16_math, None | Some(_))
| (sym::target_has_reliable_f128, None | Some(_))
| (sym::target_has_reliable_f128_math, None | Some(_))
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
(sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
(sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),

View file

@ -1,8 +1,8 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(default_field_values)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(rustc_attrs)]
// To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
// with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").

View file

@ -17,6 +17,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
@ -24,7 +25,6 @@
#![feature(core_io_borrowed_buf)]
#![feature(hash_set_entry)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(map_try_insert)]
#![feature(negative_impls)]
#![feature(read_buf)]

View file

@ -623,6 +623,7 @@ symbols! {
cfg_target_feature,
cfg_target_has_atomic,
cfg_target_has_atomic_equal_alignment,
cfg_target_has_reliable_f16_f128,
cfg_target_thread_local,
cfg_target_vendor,
cfg_trace: "<cfg>", // must not be a valid identifier
@ -2074,6 +2075,10 @@ symbols! {
target_has_atomic,
target_has_atomic_equal_alignment,
target_has_atomic_load_store,
target_has_reliable_f128,
target_has_reliable_f128_math,
target_has_reliable_f16,
target_has_reliable_f16_math,
target_os,
target_pointer_width,
target_thread_local,

View file

@ -89,9 +89,9 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -9,12 +9,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(debug_closure_helpers)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -1523,19 +1523,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return None;
};
let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_term.def_id)?;
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
let mut associated_items = vec![];
self.tcx.for_each_relevant_impl(
self.tcx.trait_of_item(proj.projection_term.def_id)?,
proj.projection_term.self_ty(),
|impl_def_id| {
associated_items.extend(
self.tcx
.associated_items(impl_def_id)
.in_definition_order()
.find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
self.tcx.associated_items(impl_def_id).in_definition_order().find(
|assoc| {
assoc.trait_item_def_id == Some(proj.projection_term.def_id)
},
),
);
},
);

View file

@ -14,6 +14,7 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@ -23,7 +24,6 @@
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(iterator_try_reduce)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]
#![feature(try_blocks)]

View file

@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@ -13,7 +14,6 @@
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iterator_try_collect)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end

View file

@ -442,6 +442,14 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
{
fn as_clause(self) -> Option<I::Clause>;
fn as_normalizes_to(self) -> Option<ty::Binder<I, ty::NormalizesTo<I>>> {
let kind = self.kind();
match kind.skip_binder() {
ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)),
_ => None,
}
}
// FIXME: Eventually uplift the impl out of rustc and make this defaulted.
fn allow_normalization(self) -> bool;
}