1
Fork 0

Auto merge of #139229 - Zalathar:rollup-5cs3f4d, r=Zalathar

Rollup of 14 pull requests

Successful merges:

 - #135295 (Check empty SIMD vector in inline asm)
 - #138003 (Add the new `amx` target features and the `movrs` target feature)
 - #138823 (rustc_target: RISC-V: add base `I`-related important extensions)
 - #138913 (Remove even more instances of `@ts-expect-error` from search.js)
 - #138941 (Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable`)
 - #139060 (replace commit placeholder in vendor status with actual commit)
 - #139102 (coverage: Avoid splitting spans during span extraction/refinement)
 - #139191 (small opaque type/borrowck cleanup)
 - #139200 (Skip suggest impl or dyn when poly trait is not a real trait)
 - #139208 (fix dead link netbsd.md)
 - #139210 (chore: remove redundant backtick)
 - #139212 (Update mdbook to 0.4.48)
 - #139214 (Tell rustfmt to use the 2024 edition in ./x.py fmt)
 - #139225 (move autodiff from EnzymeAD/Enzyme to our rust-lang/Enzyme soft-fork)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-02 03:48:21 +00:00
commit c9cd707845
117 changed files with 760 additions and 583 deletions

View file

@ -1,7 +1,7 @@
//! This file provides API for compiler consumers.
use rustc_hir::def_id::LocalDefId;
use rustc_index::{IndexSlice, IndexVec};
use rustc_index::IndexVec;
use rustc_middle::mir::{Body, Promoted};
use rustc_middle::ty::TyCtxt;
@ -100,8 +100,5 @@ pub fn get_body_with_borrowck_facts(
def: LocalDefId,
options: ConsumerOptions,
) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
*super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
*super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
}

View file

@ -103,11 +103,8 @@ pub fn provide(providers: &mut Providers) {
}
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
let (input_body, _) = tcx.mir_promoted(def);
let input_body: &Body<'_> = &input_body.borrow();
if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
debug!("Skipping borrowck because of injected body or tainted body");
// Let's make up a borrowck result! Fun times!
@ -120,7 +117,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
return tcx.arena.alloc(result);
}
let borrowck_result = do_mir_borrowck(tcx, input_body, &*promoted.borrow(), None).0;
let borrowck_result = do_mir_borrowck(tcx, def, None).0;
debug!("mir_borrowck done");
tcx.arena.alloc(borrowck_result)
@ -131,15 +128,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
/// Use `consumer_options: None` for the default behavior of returning
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
/// to the given [`ConsumerOptions`].
#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
#[instrument(skip(tcx), level = "debug")]
fn do_mir_borrowck<'tcx>(
tcx: TyCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
def: LocalDefId,
consumer_options: Option<ConsumerOptions>,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.def_id().expect_local();
let infcx = BorrowckInferCtxt::new(tcx, def);
let (input_body, promoted) = tcx.mir_promoted(def);
let input_body: &Body<'_> = &input_body.borrow();
let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
if let Some(e) = input_body.tainted_by_errors {
infcx.set_tainted_by_errors(e);
}
@ -499,7 +497,8 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
)
});
self.inject_new_hidden_type_unchecked(key, hidden_ty);
let prev = self.register_hidden_type_in_storage(key, hidden_ty);
assert_eq!(prev, None);
}
}
}

View file

@ -6,16 +6,25 @@
#![feature(gen_blocks)]
fn foo() -> impl Iterator<Item = u32> {
gen { yield 42; for x in 3..6 { yield x } }
gen {
yield 42;
for x in 3..6 {
yield x
}
}
}
fn moved() -> impl Iterator<Item = u32> {
let mut x = "foo".to_string();
gen move {
yield 42;
if x == "foo" { return }
if x == "foo" {
return;
}
x.clear();
for x in 3..6 { yield x }
for x in 3..6 {
yield x
}
}
}
@ -32,5 +41,4 @@ fn main() {
let mut iter = moved();
assert_eq!(iter.next(), Some(42));
assert_eq!(iter.next(), None);
}

View file

@ -1,7 +1,3 @@
ignore = [
"example/gen_block_iterate.rs", # uses edition 2024
]
# Matches rustfmt.toml of rustc
style_edition = "2024"
use_small_heuristics = "Max"

View file

@ -300,6 +300,13 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
("sparc", "v8plus") if get_version().0 < 19 => None,
("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
// These new `amx` variants and `movrs` were introduced in LLVM20
("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
if get_version().0 < 20 =>
{
None
}
("x86", "movrs") if get_version().0 < 20 => None,
(_, s) => Some(LLVMFeature::new(s)),
}
}

View file

@ -324,6 +324,7 @@ declare_features! (
(unstable, loongarch_target_feature, "1.73.0", Some(44839)),
(unstable, m68k_target_feature, "1.85.0", Some(134328)),
(unstable, mips_target_feature, "1.27.0", Some(44839)),
(unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)),
(unstable, powerpc_target_feature, "1.27.0", Some(44839)),
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
(unstable, riscv_target_feature, "1.45.0", Some(44839)),

View file

@ -29,6 +29,7 @@ enum NonAsmTypeReason<'tcx> {
Invalid(Ty<'tcx>),
InvalidElement(DefId, Ty<'tcx>),
NotSizedPtr(Ty<'tcx>),
EmptySIMDArray(Ty<'tcx>),
}
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
@ -102,6 +103,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
if fields.is_empty() {
return Err(NonAsmTypeReason::EmptySIMDArray(ty));
}
let field = &fields[FieldIdx::ZERO];
let elem_ty = field.ty(self.tcx(), args);
@ -226,6 +230,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
can be used as arguments for inline assembly",
).emit();
}
NonAsmTypeReason::EmptySIMDArray(ty) => {
let msg = format!("use of empty SIMD vector `{ty}`");
self.infcx.dcx().struct_span_err(expr.span, msg).emit();
}
}
return None;
}

View file

@ -86,6 +86,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
"expected a type, found a trait"
);
if self_ty.span.can_be_used_for_suggestions()
&& poly_trait_ref.trait_ref.trait_def_id().is_some()
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
&& !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
{

View file

@ -198,13 +198,12 @@ impl<'tcx> InferCtxt<'tcx> {
/// it hasn't previously been defined. This does not emit any
/// constraints and it's the responsibility of the caller to make
/// sure that the item bounds of the opaque are checked.
pub fn inject_new_hidden_type_unchecked(
pub fn register_hidden_type_in_storage(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
hidden_ty: OpaqueHiddenType<'tcx>,
) {
let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
assert_eq!(prev, None);
) -> Option<Ty<'tcx>> {
self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty)
}
/// Insert a hidden type into the opaque type storage, equating it

View file

@ -96,7 +96,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
}
} else {
// Extract coverage spans from MIR statements/terminators as normal.
extract_refined_covspans(mir_body, hir_info, graph, &mut code_mappings);
extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut code_mappings);
}
branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, graph));

View file

@ -1,7 +1,9 @@
use std::collections::VecDeque;
use std::iter;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir;
use rustc_middle::ty::TyCtxt;
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
use tracing::{debug, debug_span, instrument};
@ -11,8 +13,9 @@ use crate::coverage::{ExtractedHirInfo, mappings, unexpand};
mod from_mir;
pub(super) fn extract_refined_covspans(
mir_body: &mir::Body<'_>,
pub(super) fn extract_refined_covspans<'tcx>(
tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>,
hir_info: &ExtractedHirInfo,
graph: &CoverageGraph,
code_mappings: &mut impl Extend<mappings::CodeMapping>,
@ -50,7 +53,7 @@ pub(super) fn extract_refined_covspans(
// First, perform the passes that need macro information.
covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb));
remove_unwanted_expansion_spans(&mut covspans);
split_visible_macro_spans(&mut covspans);
shrink_visible_macro_spans(tcx, &mut covspans);
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>();
@ -83,9 +86,7 @@ pub(super) fn extract_refined_covspans(
// Split the covspans into separate buckets that don't overlap any holes.
let buckets = divide_spans_into_buckets(covspans, &holes);
for mut covspans in buckets {
// Make sure each individual bucket is internally sorted.
covspans.sort_by(compare_covspans);
for covspans in buckets {
let _span = debug_span!("processing bucket", ?covspans).entered();
let mut covspans = remove_unwanted_overlapping_spans(covspans);
@ -129,82 +130,50 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
}
/// When a span corresponds to a macro invocation that is visible from the
/// function body, split it into two parts. The first part covers just the
/// macro name plus `!`, and the second part covers the rest of the macro
/// invocation. This seems to give better results for code that uses macros.
fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
let mut extra_spans = vec![];
/// function body, truncate it to just the macro name plus `!`.
/// This seems to give better results for code that uses macros.
fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec<SpanFromMir>) {
let source_map = tcx.sess.source_map();
covspans.retain(|covspan| {
let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
return true;
};
let split_len = visible_macro.as_str().len() as u32 + 1;
let (before, after) = covspan.span.split_at(split_len);
if !covspan.span.contains(before) || !covspan.span.contains(after) {
// Something is unexpectedly wrong with the split point.
// The debug assertion in `split_at` will have already caught this,
// but in release builds it's safer to do nothing and maybe get a
// bug report for unexpected coverage, rather than risk an ICE.
return true;
for covspan in covspans {
if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) {
covspan.span = source_map.span_through_char(covspan.span, '!');
}
extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
false // Discard the original covspan that we just split.
});
// The newly-split spans are added at the end, so any previous sorting
// is not preserved.
covspans.extend(extra_spans);
}
}
/// Uses the holes to divide the given covspans into buckets, such that:
/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
/// - No span in any hole overlaps a bucket (discarding spans if necessary).
/// - The spans in each bucket are strictly after all spans in previous buckets,
/// and strictly before all spans in subsequent buckets.
///
/// The resulting buckets are sorted relative to each other, but might not be
/// internally sorted.
/// The lists of covspans and holes must be sorted.
/// The resulting buckets are sorted relative to each other, and each bucket's
/// contents are sorted.
#[instrument(level = "debug")]
fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
// Now we're ready to start carving holes out of the initial coverage spans,
// and grouping them in buckets separated by the holes.
// Now we're ready to start grouping spans into buckets separated by holes.
let mut input_covspans = VecDeque::from(input_covspans);
let mut fragments = vec![];
// For each hole:
// - Identify the spans that are entirely or partly before the hole.
// - Put those spans in a corresponding bucket, truncated to the start of the hole.
// - If one of those spans also extends after the hole, put the rest of it
// in a "fragments" vector that is processed by the next hole.
// - Discard any that overlap with the hole.
// - Add the remaining identified spans to the corresponding bucket.
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
for (hole, bucket) in holes.iter().zip(&mut buckets) {
let fragments_from_prev = std::mem::take(&mut fragments);
// Only inspect spans that precede or overlap this hole,
// leaving the rest to be inspected by later holes.
// (This relies on the spans and holes both being sorted.)
let relevant_input_covspans =
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
let (before, after) = covspan.split_around_hole_span(hole.span);
bucket.extend(before);
fragments.extend(after);
}
bucket.extend(
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi())
.filter(|c| !c.span.overlaps(hole.span)),
);
}
// After finding the spans before each hole, any remaining fragments/spans
// form their own final bucket, after the final hole.
// Any remaining spans form their own final bucket, after the final hole.
// (If there were no holes, this will just be all of the initial spans.)
fragments.extend(input_covspans);
buckets.push(fragments);
buckets.push(Vec::from(input_covspans));
buckets
}
@ -215,7 +184,7 @@ fn drain_front_while<'a, T>(
queue: &'a mut VecDeque<T>,
mut pred_fn: impl FnMut(&T) -> bool,
) -> impl Iterator<Item = T> {
std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x)))
}
/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
@ -258,22 +227,6 @@ struct Covspan {
}
impl Covspan {
/// Splits this covspan into 0-2 parts:
/// - The part that is strictly before the hole span, if any.
/// - The part that is strictly after the hole span, if any.
fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
let before = try {
let span = self.span.trim_end(hole_span)?;
Self { span, ..*self }
};
let after = try {
let span = self.span.trim_start(hole_span)?;
Self { span, ..*self }
};
(before, after)
}
/// If `self` and `other` can be merged (i.e. they have the same BCB),
/// mutates `self.span` to also include `other.span` and returns true.
///

View file

@ -120,22 +120,20 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
// an `if condition { block }` has a span that includes the executed block, if true,
// but for coverage, the code region executed, up to *and* through the SwitchInt,
// actually stops before the if's block.)
TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
TerminatorKind::Unreachable
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::SwitchInt { .. }
// For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::Goto { .. } => None,
// Call `func` operand can have a more specific span when part of a chain of calls
TerminatorKind::Call { ref func, .. }
| TerminatorKind::TailCall { ref func, .. } => {
TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => {
let mut span = terminator.source_info.span;
if let mir::Operand::Constant(box constant) = func {
if constant.span.lo() > span.lo() {
span = span.with_lo(constant.span.lo());
}
if let mir::Operand::Constant(constant) = func
&& span.contains(constant.span)
{
span = constant.span;
}
Some(span)
}
@ -147,9 +145,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
| TerminatorKind::Yield { .. }
| TerminatorKind::CoroutineDrop
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. } => {
Some(terminator.source_info.span)
}
| TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
}
}

View file

@ -12,6 +12,7 @@
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(vec_deque_pop_if)]
#![feature(yeet_expr)]
// tidy-alphabetical-end

View file

@ -62,14 +62,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> <Self::Interner as Interner>::GenericArg;
// FIXME: Can we implement this in terms of `add` and `inject`?
fn insert_hidden_type(
fn register_hidden_type_in_storage(
&self,
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
param_env: <Self::Interner as Interner>::ParamEnv,
hidden_ty: <Self::Interner as Interner>::Ty,
goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
) -> Result<(), NoSolution>;
span: <Self::Interner as Interner>::Span,
) -> Option<<Self::Interner as Interner>::Ty>;
fn add_item_bounds_for_hidden_type(
&self,
@ -79,14 +77,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
hidden_ty: <Self::Interner as Interner>::Ty,
goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
);
fn inject_new_hidden_type_unchecked(
&self,
key: ty::OpaqueTypeKey<Self::Interner>,
hidden_ty: <Self::Interner as Interner>::Ty,
span: <Self::Interner as Interner>::Span,
);
fn reset_opaque_types(&self);
fn fetch_eligible_assoc_item(

View file

@ -425,7 +425,8 @@ where
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
for &(key, ty) in opaque_types {
self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span);
let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
assert_eq!(prev, None);
}
}
}

View file

@ -387,7 +387,8 @@ where
};
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
assert_eq!(prev, None);
}
if !ecx.nested_goals.is_empty() {
@ -1070,16 +1071,12 @@ where
self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
}
pub(super) fn insert_hidden_type(
pub(super) fn register_hidden_type_in_storage(
&mut self,
opaque_type_key: ty::OpaqueTypeKey<I>,
param_env: I::ParamEnv,
hidden_ty: I::Ty,
) -> Result<(), NoSolution> {
let mut goals = Vec::new();
self.delegate.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?;
self.add_goals(GoalSource::Misc, goals);
Ok(())
) -> Option<I::Ty> {
self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span)
}
pub(super) fn add_item_bounds_for_hidden_type(

View file

@ -86,8 +86,8 @@ where
}
// Otherwise, define a new opaque type
// FIXME: should we use `inject_hidden_type_unchecked` here?
self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
assert_eq!(prev, None);
self.add_item_bounds_for_hidden_type(
def_id.into(),
opaque_ty.args,

View file

@ -1378,6 +1378,7 @@ symbols! {
movbe_target_feature,
move_ref_pattern,
move_size_limit,
movrs_target_feature,
mul,
mul_assign,
mul_with_overflow,

View file

@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},

View file

@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),

View file

@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),

View file

@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c,+zba,+zbb,+zbs,+v".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei,+zba,+zbb,+zbs,+v".into(),
llvm_abiname: "lp64d".into(),
supported_sanitizers: SanitizerSet::ADDRESS,
max_atomic_width: Some(64),

View file

@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv64".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},

View file

@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..base::freebsd::opts()

View file

@ -4,7 +4,7 @@ pub(crate) fn target() -> Target {
let mut base = base::fuchsia::opts();
base.code_model = Some(CodeModel::Medium);
base.cpu = "generic-rv64".into();
base.features = "+m,+a,+f,+d,+c".into();
base.features = "+m,+a,+f,+d,+c,+zicsr,+zifencei".into();
base.llvm_abiname = "lp64d".into();
base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;

View file

@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
options: TargetOptions {
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
relocation_model: RelocModel::Pic,
code_model: Some(CodeModel::Medium),
tls_model: TlsModel::LocalExec,

View file

@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),

View file

@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),

View file

@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
mcount: "__mcount".into(),

View file

@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View file

@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View file

@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
features: "+m,+a,+f,+d,+c".into(),
features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..base::openbsd::opts()

View file

@ -380,11 +380,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
("adx", Stable, &[]),
("aes", Stable, &["sse2"]),
("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("avx", Stable, &["sse4.2"]),
("avx2", Stable, &["avx"]),
("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
@ -418,6 +423,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", Stable, &[]),
("movbe", Stable, &[]),
("movrs", Unstable(sym::movrs_target_feature), &[]),
("pclmulqdq", Stable, &["sse2"]),
("popcnt", Stable, &[]),
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
@ -488,7 +494,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("c", Stable, &[]),
("d", Unstable(sym::riscv_target_feature), &["f"]),
("e", Unstable(sym::riscv_target_feature), &[]),
("f", Unstable(sym::riscv_target_feature), &[]),
("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
(
"forced-atomics",
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
@ -517,15 +523,20 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
("zfinx", Unstable(sym::riscv_target_feature), &[]),
("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
("zicntr", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zicsr", Unstable(sym::riscv_target_feature), &[]),
("zifencei", Unstable(sym::riscv_target_feature), &[]),
("zihintpause", Unstable(sym::riscv_target_feature), &[]),
("zihpm", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zk", Stable, &["zkn", "zkr", "zkt"]),
("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
("zknd", Stable, &[]),
("zkne", Stable, &[]),
("zknh", Stable, &[]),
("zkr", Stable, &[]),
("zkr", Stable, &["zicsr"]),
("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
("zksed", Stable, &[]),
("zksh", Stable, &[]),
@ -533,7 +544,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b"]),
("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),

View file

@ -149,16 +149,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
self.0.instantiate_canonical_var(span, cv_info, universe_map)
}
fn insert_hidden_type(
fn register_hidden_type_in_storage(
&self,
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> Result<(), NoSolution> {
self.0
.insert_hidden_type(opaque_type_key, DUMMY_SP, param_env, hidden_ty, goals)
.map_err(|_| NoSolution)
opaque_type_key: rustc_type_ir::OpaqueTypeKey<Self::Interner>,
hidden_ty: <Self::Interner as ty::Interner>::Ty,
span: <Self::Interner as ty::Interner>::Span,
) -> Option<<Self::Interner as ty::Interner>::Ty> {
self.0.register_hidden_type_in_storage(
opaque_type_key,
ty::OpaqueHiddenType { span, ty: hidden_ty },
)
}
fn add_item_bounds_for_hidden_type(
@ -172,15 +172,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals);
}
fn inject_new_hidden_type_unchecked(
&self,
key: ty::OpaqueTypeKey<'tcx>,
hidden_ty: Ty<'tcx>,
span: Span,
) {
self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { ty: hidden_ty, span })
}
fn reset_opaque_types(&self) {
let _ = self.take_opaque_types();
}

View file

@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
let param_env = {
let param_env = tcx.param_env(method.def_id);
// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
// in the param-env query here. The fact that we don't just start with the clauses
// in the param-env of the method is because those are already normalized, and mixing
// normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
// will cause ambiguity that the user can't really avoid.
//
// We leave out certain complexities of the param-env query here. Specifically, we:
// 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
// 2. Do not add RPITIT self projection bounds for defaulted methods, since we
// are not constructing a param-env for "inside" of the body of the defaulted
// method, so we don't really care about projecting to a specific RPIT type,
// and because RPITITs are not dyn compatible (yet).
let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
// Self: Unsize<U>
let unsize_predicate =
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
predicates.push(unsize_predicate.upcast(tcx));
// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
let trait_def_id = method.trait_container(tcx).unwrap();
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
});
ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
};
let trait_def_id = method.trait_container(tcx).unwrap();
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
});
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
predicates.push(trait_predicate.upcast(tcx));
normalize_param_env_or_error(
tcx,
ty::ParamEnv::new(tcx.mk_clauses_from_iter(
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
)),
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
)
};