Auto merge of #151087 - GuillaumeGomez:rollup-vIdiReJ, r=GuillaumeGomez

Rollup of 13 pull requests

Successful merges:

 - rust-lang/rust#150587 (triagebot: add A-rustdoc-js autolabel)
 - rust-lang/rust#150677 (Improve std::path::Path::join documentation)
 - rust-lang/rust#150737 (diagnostics: make implicit Sized bounds explicit in E0277)
 - rust-lang/rust#150771 (Remove legacy homu `try` and `auto` branch mentions)
 - rust-lang/rust#150840 (Make `--print=check-cfg` output compatible `--check-cfg` arguments)
 - rust-lang/rust#150915 (Regression test for type params on eii)
 - rust-lang/rust#151017 (Port the rustc dump attributes to the attribute parser)
 - rust-lang/rust#151019 (Make `Type::of` support unsized types)
 - rust-lang/rust#151031 (Support arrays in type reflection)
 - rust-lang/rust#151043 (armv7-unknown-linux-uclibceabihf.md: Fix bootstrap.toml syntax)
 - rust-lang/rust#151052 (ui: add regression test for macro resolution ICE (issue rust-lang/rust#150711))
 - rust-lang/rust#151053 (Reduce flakyness for `tests/rustdoc-gui/notable-trait.goml`)
 - rust-lang/rust#151055 (Emit error instead of delayed bug when meeting mismatch type for const array)

r? @ghost
This commit is contained in:
bors 2026-01-14 03:26:31 +00:00
commit 4931e09e3a
52 changed files with 727 additions and 174 deletions

View file

@ -11,11 +11,9 @@ name: CI
on:
push:
branches:
- auto
- try
- try-perf
- automation/bors/try
- automation/bors/auto
- automation/bors/try
- try-perf
pull_request:
branches:
- "**"
@ -33,9 +31,10 @@ defaults:
concurrency:
# For a given workflow, if we push to the same branch, cancel all previous builds on that branch.
# We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which
# are all triggered on the same branch, but which should be able to run concurrently.
group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try') && github.sha) || github.ref }}
# We add an exception for try builds (automation/bors/try branch) and unrolled rollup builds
# (try-perf), which are all triggered on the same branch, but which should be able to run
# concurrently.
group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try') && github.sha) || github.ref }}
cancel-in-progress: true
env:
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
@ -57,7 +56,7 @@ jobs:
- name: Test citool
# Only test citool on the auto branch, to reduce latency of the calculate matrix job
# on PR/try builds.
if: ${{ github.ref == 'refs/heads/auto' || github.ref == 'refs/heads/automation/bors/auto' }}
if: ${{ github.ref == 'refs/heads/automation/bors/auto' }}
run: |
cd src/ci/citool
CARGO_INCREMENTAL=0 cargo test
@ -80,7 +79,7 @@ jobs:
# access the environment.
#
# We only enable the environment for the rust-lang/rust repository, so that CI works on forks.
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/auto' || github.ref == 'refs/heads/automation/bors/auto')) && 'bors') || '' }}
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/automation/bors/auto')) && 'bors') || '' }}
env:
CI_JOB_NAME: ${{ matrix.name }}
CI_JOB_DOC_URL: ${{ matrix.doc_url }}
@ -314,7 +313,7 @@ jobs:
needs: [ calculate_matrix, job ]
# !cancelled() executes the job regardless of whether the previous jobs passed or failed
if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }}
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/auto' || github.ref == 'refs/heads/automation/bors/auto')) && 'bors') || '' }}
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/automation/bors/auto')) && 'bors') || '' }}
steps:
- name: checkout the source code
uses: actions/checkout@v5

View file

@ -57,6 +57,7 @@ pub(crate) mod pin_v2;
pub(crate) mod proc_macro_attrs;
pub(crate) mod prototype;
pub(crate) mod repr;
pub(crate) mod rustc_dump;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;
pub(crate) mod stability;

View file

@ -0,0 +1,62 @@
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use crate::attributes::prelude::Allow;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::Stage;
use crate::target_checking::AllowedTargets;
pub(crate) struct RustcDumpUserArgs;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpUserArgs {
const PATH: &[Symbol] = &[sym::rustc_dump_user_args];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs;
}
pub(crate) struct RustcDumpDefParents;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParents {
const PATH: &[Symbol] = &[sym::rustc_dump_def_parents];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents;
}
pub(crate) struct RustcDumpItemBounds;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBounds {
const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds;
}
pub(crate) struct RustcDumpPredicates;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicates {
const PATH: &[Symbol] = &[sym::rustc_dump_predicates];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::Union),
Allow(Target::Trait),
Allow(Target::AssocTy),
]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates;
}
pub(crate) struct RustcDumpVtable;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVtable {
const PATH: &[Symbol] = &[sym::rustc_dump_vtable];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Impl { of_trait: true }),
Allow(Target::TyAlias),
]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDumpVtable;
}

View file

@ -63,6 +63,10 @@ use crate::attributes::proc_macro_attrs::{
};
use crate::attributes::prototype::CustomMirParser;
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
use crate::attributes::rustc_dump::{
RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs,
RustcDumpVtable,
};
use crate::attributes::rustc_internal::{
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
@ -267,6 +271,11 @@ attribute_parsers!(
Single<WithoutArgs<ProcMacroParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
Single<WithoutArgs<RustcDumpDefParents>>,
Single<WithoutArgs<RustcDumpItemBounds>>,
Single<WithoutArgs<RustcDumpPredicates>>,
Single<WithoutArgs<RustcDumpUserArgs>>,
Single<WithoutArgs<RustcDumpVtable>>,
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
Single<WithoutArgs<RustcLintDiagnosticsParser>>,
Single<WithoutArgs<RustcLintOptTyParser>>,

View file

@ -3,7 +3,7 @@ use rustc_hir::LangItem;
use rustc_middle::mir::interpret::CtfeProvenance;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, ScalarInt, Ty};
use rustc_middle::ty::{self, Const, ScalarInt, Ty};
use rustc_span::{Symbol, sym};
use crate::const_eval::CompileTimeMachine;
@ -56,6 +56,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
self.write_tuple_fields(tuple_place, fields, ty)?;
variant
}
ty::Array(ty, len) => {
let (variant, variant_place) = downcast(sym::Array)?;
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
self.write_array_type_info(array_place, *ty, *len)?;
variant
}
// For now just merge all primitives into one `Leaf` variant with no data
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char | ty::Bool => {
downcast(sym::Leaf)?.0
@ -63,7 +71,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
ty::Adt(_, _)
| ty::Foreign(_)
| ty::Str
| ty::Array(_, _)
| ty::Pat(_, _)
| ty::Slice(_)
| ty::RawPtr(..)
@ -172,4 +179,28 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
}
interp_ok(())
}
pub(crate) fn write_array_type_info(
&mut self,
place: impl Writeable<'tcx, CtfeProvenance>,
ty: Ty<'tcx>,
len: Const<'tcx>,
) -> InterpResult<'tcx> {
// Iterate over all fields of `type_info::Array`.
for (field_idx, field) in
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
{
let field_place = self.project_field(&place, field_idx)?;
match field.name {
// Write the `TypeId` of the array's elements to the `element_ty` field.
sym::element_ty => self.write_type_id(ty, &field_place)?,
// Write the length of the array to the `len` field.
sym::len => self.write_scalar(len.to_leaf(), &field_place)?,
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
}
interp_ok(())
}
}

View file

@ -765,30 +765,35 @@ fn print_crate_info(
for (name, expected_values) in &sess.psess.check_config.expecteds {
use crate::config::ExpectedValues;
match expected_values {
ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")),
ExpectedValues::Any => {
check_cfgs.push(format!("cfg({name}, values(any()))"))
}
ExpectedValues::Some(values) => {
if !values.is_empty() {
check_cfgs.extend(values.iter().map(|value| {
let mut values: Vec<_> = values
.iter()
.map(|value| {
if let Some(value) = value {
format!("{name}=\"{value}\"")
format!("\"{value}\"")
} else {
name.to_string()
"none()".to_string()
}
}))
} else {
check_cfgs.push(format!("{name}="))
}
})
.collect();
values.sort_unstable();
let values = values.join(", ");
check_cfgs.push(format!("cfg({name}, values({values}))"))
}
}
}
check_cfgs.sort_unstable();
if !sess.psess.check_config.exhaustive_names {
if !sess.psess.check_config.exhaustive_values {
println_info!("any()=any()");
} else {
println_info!("any()");
}
if !sess.psess.check_config.exhaustive_names
&& sess.psess.check_config.exhaustive_values
{
println_info!("cfg(any())");
}
for check_cfg in check_cfgs {
println_info!("{check_cfg}");

View file

@ -906,6 +906,21 @@ pub enum AttributeKind {
/// Represents `#[rustc_coherence_is_core]`
RustcCoherenceIsCore(Span),
/// Represents `#[rustc_dump_def_parents]`
RustcDumpDefParents,
/// Represents `#[rustc_dump_item_bounds]`
RustcDumpItemBounds,
/// Represents `#[rustc_dump_predicates]`
RustcDumpPredicates,
/// Represents `#[rustc_dump_user_args]`
RustcDumpUserArgs,
/// Represents `#[rustc_dump_vtable]`
RustcDumpVtable(Span),
/// Represents `#[rustc_has_incoherent_inherent_impls]`
RustcHasIncoherentInherentImpls,

View file

@ -97,6 +97,11 @@ impl AttributeKind {
Repr { .. } => No,
RustcBuiltinMacro { .. } => Yes,
RustcCoherenceIsCore(..) => No,
RustcDumpDefParents => No,
RustcDumpItemBounds => No,
RustcDumpPredicates => No,
RustcDumpUserArgs => No,
RustcDumpVtable(..) => No,
RustcHasIncoherentInherentImpls => Yes,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,

View file

@ -166,8 +166,9 @@ hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twic
.label = parameter captured again here
hir_analysis_eii_with_generics =
#[{$eii_name}] cannot have generic parameters other than lifetimes
`{$impl_name}` cannot have generic parameters other than lifetimes
.label = required by this attribute
.help = `#[{$eii_name}]` marks the implementation of an "externally implementable item"
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
.note = impl is a specialization of this impl

View file

@ -974,12 +974,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
(0, _) => ("const", "consts", None),
_ => ("type or const", "types or consts", None),
};
let name =
if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::EiiForeignItem) {
"externally implementable items"
} else {
"foreign items"
};
let span = tcx.def_span(def_id);
struct_span_code_err!(
tcx.dcx(),
span,
E0044,
"foreign items may not have {kinds} parameters",
"{name} may not have {kinds} parameters",
)
.with_span_label(span, format!("can't have {kinds} parameters"))
.with_help(

View file

@ -8,8 +8,9 @@ use std::iter;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, E0806, struct_span_code_err};
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, FnSig, HirId, ItemKind};
use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr};
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -169,11 +170,23 @@ fn check_no_generics<'tcx>(
eii_attr_span: Span,
) -> Result<(), ErrorGuaranteed> {
let generics = tcx.generics_of(external_impl);
if generics.own_requires_monomorphization() {
if generics.own_requires_monomorphization()
// When an EII implementation is automatically generated by the `#[eii]` macro,
// it will directly refer to the foreign item, not through a macro.
// We don't want to emit this error if it's an implementation that's generated by the `#[eii]` macro,
// since in that case it looks like a duplicate error: the declaration of the EII already can't contain generics.
// So, we check here if at least one of the eii impls has ImplResolution::Macro, which indicates it's
// not generated as part of the declaration.
&& find_attr!(
tcx.get_all_attrs(external_impl),
AttributeKind::EiiImpls(impls) if impls.iter().any(|i| matches!(i.resolution, EiiImplResolution::Macro(_)))
)
{
tcx.dcx().emit_err(EiiWithGenerics {
span: tcx.def_span(external_impl),
attr: eii_attr_span,
eii_name,
impl_name: tcx.item_name(external_impl),
});
}

View file

@ -1,6 +1,7 @@
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::intravisit;
use rustc_hir::{find_attr, intravisit};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
@ -28,7 +29,7 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
for id in tcx.hir_crate_items(()).owners() {
if tcx.has_attr(id, sym::rustc_dump_predicates) {
if find_attr!(tcx.get_all_attrs(id), AttributeKind::RustcDumpPredicates) {
let preds = tcx.predicates_of(id).instantiate_identity(tcx).predicates;
let span = tcx.def_span(id);
@ -38,7 +39,7 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
}
diag.emit();
}
if tcx.has_attr(id, sym::rustc_dump_item_bounds) {
if find_attr!(tcx.get_all_attrs(id), AttributeKind::RustcDumpItemBounds) {
let bounds = tcx.item_bounds(id).instantiate_identity();
let span = tcx.def_span(id);
@ -54,7 +55,7 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
for iid in tcx.hir_free_items() {
let did = iid.owner_id.def_id;
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
if find_attr!(tcx.get_all_attrs(did), AttributeKind::RustcDumpDefParents) {
struct AnonConstFinder<'tcx> {
tcx: TyCtxt<'tcx>,
anon_consts: Vec<LocalDefId>,
@ -102,7 +103,9 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
for id in tcx.hir_free_items() {
let def_id = id.owner_id.def_id;
let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else {
let Some(&attr_span) =
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcDumpVtable(span) => span)
else {
continue;
};
@ -111,14 +114,14 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
let trait_ref = tcx.impl_trait_ref(def_id).instantiate_identity();
if trait_ref.has_non_region_param() {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` must be applied to non-generic impl",
);
continue;
}
if !tcx.is_dyn_compatible(trait_ref.def_id) {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` must be applied to dyn-compatible trait",
);
continue;
@ -127,7 +130,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref)
else {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` applied to impl header that cannot be normalized",
);
continue;
@ -138,7 +141,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
let ty = tcx.type_of(def_id).instantiate_identity();
if ty.has_non_region_param() {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` must be applied to non-generic type",
);
continue;
@ -147,14 +150,13 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
else {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` applied to type alias that cannot be normalized",
);
continue;
};
let ty::Dynamic(data, _) = *ty.kind() else {
tcx.dcx()
.span_err(attr.span(), "`rustc_dump_vtable` to type alias of dyn type");
tcx.dcx().span_err(attr_span, "`rustc_dump_vtable` to type alias of dyn type");
continue;
};
if let Some(principal) = data.principal() {
@ -167,7 +169,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
}
_ => {
tcx.dcx().span_err(
attr.span(),
attr_span,
"`rustc_dump_vtable` only applies to impl, or type alias of dyn type",
);
continue;

View file

@ -1655,10 +1655,12 @@ pub(crate) struct LifetimesOrBoundsMismatchOnEii {
#[derive(Diagnostic)]
#[diag(hir_analysis_eii_with_generics)]
#[help]
pub(crate) struct EiiWithGenerics {
#[primary_span]
pub span: Span,
#[label]
pub attr: Span,
pub eii_name: Symbol,
pub impl_name: Symbol,
}

View file

@ -2415,11 +2415,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
};
let ty::Array(elem_ty, _) = ty.kind() else {
return Const::new_error_with_message(
tcx,
array_expr.span,
"const array must have an array type",
);
let e = tcx
.dcx()
.span_err(array_expr.span, format!("expected `{}`, found const array", ty));
return Const::new_error(tcx, e);
};
let elems = array_expr

View file

@ -14,9 +14,10 @@ use std::ops::ControlFlow;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::{E0720, ErrorGuaranteed};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_hir::{self as hir, AmbigArg, HirId, find_attr};
use rustc_infer::traits::solve::Goal;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@ -25,7 +26,7 @@ use rustc_middle::ty::{
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
fold_regions,
};
use rustc_span::{Span, sym};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::opaque_types::opaque_type_has_defining_use_args;
use rustc_trait_selection::solve;
@ -45,8 +46,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
let rustc_dump_user_args =
self.has_rustc_attrs && self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
let rustc_dump_user_args = self.has_rustc_attrs
&& find_attr!(self.tcx.get_all_attrs(item_def_id), AttributeKind::RustcDumpUserArgs);
let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args);
for param in body.params {

View file

@ -309,6 +309,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::CfiEncoding { .. }
| AttributeKind::RustcHasIncoherentInherentImpls
| AttributeKind::MustNotSupend { .. }
| AttributeKind::RustcDumpUserArgs
| AttributeKind::RustcDumpItemBounds
| AttributeKind::RustcDumpPredicates
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpVtable(..)
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -368,25 +373,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::rustc_abi
| sym::rustc_layout
| sym::rustc_proc_macro_decls
| sym::rustc_dump_def_parents
| sym::rustc_never_type_options
| sym::rustc_autodiff
| sym::rustc_capture_analysis
| sym::rustc_regions
| sym::rustc_strict_coherence
| sym::rustc_dump_predicates
| sym::rustc_variance
| sym::rustc_variance_of_opaques
| sym::rustc_hidden_type_of_opaques
| sym::rustc_mir
| sym::rustc_dump_user_args
| sym::rustc_effective_visibility
| sym::rustc_outlives
| sym::rustc_symbol_name
| sym::rustc_evaluate_where_clauses
| sym::rustc_dump_vtable
| sym::rustc_delayed_bug_from_inside_query
| sym::rustc_dump_item_bounds
| sym::rustc_def_path
| sym::rustc_partition_reused
| sym::rustc_partition_codegened

View file

@ -162,6 +162,7 @@ symbols! {
Arc,
ArcWeak,
Argument,
Array,
ArrayIntoIter,
AsMut,
AsRef,
@ -939,6 +940,7 @@ symbols! {
eii_impl,
eii_internals,
eii_shared_macro,
element_ty,
emit,
emit_enum,
emit_enum_variant,

View file

@ -1391,25 +1391,45 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// return early in the caller.
let mut label = || {
// Special case `Sized` as `old_pred` will be the trait itself instead of
// `Sized` when the trait bound is the source of the error.
let is_sized = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
}
_ => false,
};
let msg = format!(
"the trait bound `{}` is not satisfied",
self.tcx.short_string(old_pred, err.long_ty_path()),
);
let self_ty_str =
self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
let self_ty_str = self.tcx.short_string(old_pred.self_ty(), err.long_ty_path());
let trait_path = self
.tcx
.short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
if has_custom_message {
let msg = if is_sized {
"the trait bound `Sized` is not satisfied".into()
} else {
msg
};
err.note(msg);
} else {
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
}
err.span_label(
span,
format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
);
if is_sized {
err.span_label(
span,
format!("the trait `Sized` is not implemented for `{self_ty_str}`"),
);
} else {
err.span_label(
span,
format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
);
}
};
let mut sugg_prefixes = vec![];
@ -3578,10 +3598,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
"unsatisfied trait bound introduced in this `derive` macro",
);
} else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) {
spans.push_span_label(
data.span,
"unsatisfied trait bound introduced here",
);
// `Sized` may be an explicit or implicit trait bound. If it is
// implicit, mention it as such.
if let Some(pred) = predicate.as_trait_clause()
&& self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
&& self
.tcx
.generics_of(data.impl_or_alias_def_id)
.own_params
.iter()
.any(|param| self.tcx.def_span(param.def_id) == data.span)
{
spans.push_span_label(
data.span,
"unsatisfied trait bound implicitly introduced here",
);
} else {
spans.push_span_label(
data.span,
"unsatisfied trait bound introduced here",
);
}
}
err.span_note(spans, msg);
point_at_assoc_type_restriction(

View file

@ -31,7 +31,7 @@ impl Type {
#[unstable(feature = "type_info", issue = "146922")]
#[rustc_const_unstable(feature = "type_info", issue = "146922")]
// FIXME(reflection): don't require the 'static bound
pub const fn of<T: 'static>() -> Self {
pub const fn of<T: ?Sized + 'static>() -> Self {
const { TypeId::of::<T>().info() }
}
}
@ -43,6 +43,8 @@ impl Type {
pub enum TypeKind {
/// Tuples.
Tuple(Tuple),
/// Arrays.
Array(Array),
/// Primitives
/// FIXME(#146922): disambiguate further
Leaf,
@ -69,3 +71,14 @@ pub struct Field {
/// Offset in bytes from the parent type
pub offset: usize,
}
/// Compile-time type information about arrays.
#[derive(Debug)]
#[non_exhaustive]
#[unstable(feature = "type_info", issue = "146922")]
pub struct Array {
/// The type of each element in the array.
pub element_ty: TypeId,
/// The length of the array.
pub len: usize,
}

View file

@ -115,6 +115,7 @@
#![feature(try_blocks)]
#![feature(try_find)]
#![feature(try_trait_v2)]
#![feature(type_info)]
#![feature(uint_bit_width)]
#![feature(uint_gather_scatter_bits)]
#![feature(unsize)]

View file

@ -1,3 +1,5 @@
mod type_info;
use core::mem::*;
use core::{array, ptr};
use std::cell::Cell;

View file

@ -0,0 +1,56 @@
use std::any::TypeId;
use std::mem::type_info::{Type, TypeKind};
#[test]
fn test_arrays() {
// Normal array.
match const { Type::of::<[u16; 4]>() }.kind {
TypeKind::Array(array) => {
assert_eq!(array.element_ty, TypeId::of::<u16>());
assert_eq!(array.len, 4);
}
_ => unreachable!(),
}
// Zero-length array.
match const { Type::of::<[bool; 0]>() }.kind {
TypeKind::Array(array) => {
assert_eq!(array.element_ty, TypeId::of::<bool>());
assert_eq!(array.len, 0);
}
_ => unreachable!(),
}
}
#[test]
fn test_tuples() {
fn assert_tuple_arity<T: 'static, const N: usize>() {
match const { Type::of::<T>() }.kind {
TypeKind::Tuple(tup) => {
assert_eq!(tup.fields.len(), N);
}
_ => unreachable!(),
}
}
assert_tuple_arity::<(), 0>();
assert_tuple_arity::<(u8,), 1>();
assert_tuple_arity::<(u8, u8), 2>();
const {
match Type::of::<(u8, u8)>().kind {
TypeKind::Tuple(tup) => {
let [a, b] = tup.fields else { unreachable!() };
assert!(a.offset == 0);
assert!(b.offset == 1);
match (a.ty.info().kind, b.ty.info().kind) {
(TypeKind::Leaf, TypeKind::Leaf) => {}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
}

View file

@ -2972,6 +2972,15 @@ impl Path {
///
/// If `path` is absolute, it replaces the current path.
///
/// On Windows:
///
/// * if `path` has a root but no prefix (e.g., `\windows`), it
/// replaces and returns everything except for the prefix (if any) of `self`.
/// * if `path` has a prefix but no root, `self` is ignored and `path` is returned.
/// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`)
/// and `path` is not empty, the new path is normalized: all references
/// to `.` and `..` are removed.
///
/// See [`PathBuf::push`] for more details on what it means to adjoin a path.
///
/// # Examples

View file

@ -41,14 +41,12 @@ impl GitHubContext {
match (self.event_name.as_str(), self.branch_ref.as_str()) {
("pull_request", _) => Some(RunType::PullRequest),
("push", "refs/heads/try-perf") => Some(RunType::TryJob { job_patterns: None }),
("push", "refs/heads/try" | "refs/heads/automation/bors/try") => {
("push", "refs/heads/automation/bors/try") => {
let patterns = self.get_try_job_patterns();
let patterns = if !patterns.is_empty() { Some(patterns) } else { None };
Some(RunType::TryJob { job_patterns: patterns })
}
("push", "refs/heads/auto" | "refs/heads/automation/bors/auto") => {
Some(RunType::AutoJob)
}
("push", "refs/heads/automation/bors/auto") => Some(RunType::AutoJob),
("push", "refs/heads/main") => Some(RunType::MainJob),
_ => None,
}

View file

@ -4,7 +4,7 @@ const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/tes
#[test]
fn auto_jobs() {
let stdout = get_matrix("push", "commit", "refs/heads/auto");
let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/auto");
insta::assert_snapshot!(stdout, @r#"
jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","SELECT_XCODE":"/Applications/Xcode_15.4.app","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}]
run_type=auto
@ -13,7 +13,7 @@ fn auto_jobs() {
#[test]
fn try_jobs() {
let stdout = get_matrix("push", "commit", "refs/heads/try");
let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/try");
insta::assert_snapshot!(stdout, @r###"
jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}]
run_type=try
@ -28,7 +28,7 @@ fn try_custom_jobs() {
try-job: aarch64-gnu
try-job: dist-i686-msvc"#,
"refs/heads/try",
"refs/heads/automation/bors/try",
);
insta::assert_snapshot!(stdout, @r###"
jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}]

View file

@ -8,8 +8,7 @@ IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
if isCiBranch auto || isCiBranch try || isCiBranch try-perf || \
isCiBranch automation/bors/try || isCiBranch automation/bors/auto; then
if isCiBranch try-perf || isCiBranch automation/bors/try || isCiBranch automation/bors/auto; then
echo "channel verification is only executed on PR builds"
exit
fi

View file

@ -21,7 +21,7 @@ This target is cross compiled, and requires a cross toolchain. You can find sui
Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them.
If you don't already have a suitable toolchain, download one [here](https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--bleeding-edge-2021.11-1.tar.bz2), and unpack it into a directory.
If you don't already have a suitable toolchain, download one [here](https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--bleeding-edge-2025.08-1.tar.xz), and unpack it into a directory.
### Configure rust
@ -30,7 +30,7 @@ The target can be built by enabling it for a `rustc` build, by placing the follo
```toml
[build]
target = ["armv7-unknown-linux-uclibceabihf"]
stage = 2
build-stage = 2
[target.armv7-unknown-linux-uclibceabihf]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN

View file

@ -9,18 +9,20 @@ This option of the `--print` flag print the list of all the expected cfgs.
This is related to the [`--check-cfg` flag][check-cfg] which allows specifying arbitrary expected
names and values.
This print option works similarly to `--print=cfg` (modulo check-cfg specifics).
This print option outputs compatible `--check-cfg` arguments with a reduced syntax where all the
expected values are on the same line and `values(...)` is always explicit.
| `--check-cfg` | `--print=check-cfg` |
|-----------------------------------|-----------------------------|
| `cfg(foo)` | `foo` |
| `cfg(foo, values("bar"))` | `foo="bar"` |
| `cfg(foo, values(none(), "bar"))` | `foo` & `foo="bar"` |
| | *check-cfg specific syntax* |
| `cfg(foo, values(any())` | `foo=any()` |
| `cfg(foo, values())` | `foo=` |
| `cfg(any())` | `any()` |
| *none* | `any()=any()` |
| `--check-cfg` | `--print=check-cfg` |
|-----------------------------------|-----------------------------------|
| `cfg(foo)` | `cfg(foo, values(none())) |
| `cfg(foo, values("bar"))` | `cfg(foo, values("bar"))` |
| `cfg(foo, values(none(), "bar"))` | `cfg(foo, values(none(), "bar"))` |
| `cfg(foo, values(any())` | `cfg(foo, values(any())` |
| `cfg(foo, values())` | `cfg(foo, values())` |
| `cfg(any())` | `cfg(any())` |
| *nothing* | *nothing* |
The print option includes well known cfgs.
To be used like this:
@ -28,4 +30,7 @@ To be used like this:
rustc --print=check-cfg -Zunstable-options lib.rs
```
> **Note:** Users should be resilient when parsing, in particular against new predicates that
may be added in the future.
[check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html

View file

@ -1070,11 +1070,27 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
Default::default(),
)
.lines()
.map(|l| if let Some((name, _)) = l.split_once('=') { name.to_string() } else { l.to_string() })
.map(|l| extract_cfg_name(&l).unwrap().to_string())
.chain(std::iter::once(String::from("test")))
.collect()
}
/// Extract the cfg name from `cfg(name, values(...))` lines
fn extract_cfg_name(check_cfg_line: &str) -> Result<&str, &'static str> {
let trimmed = check_cfg_line.trim();
#[rustfmt::skip]
let inner = trimmed
.strip_prefix("cfg(")
.ok_or("missing cfg(")?
.strip_suffix(")")
.ok_or("missing )")?;
let first_comma = inner.find(',').ok_or("no comma found")?;
Ok(inner[..first_comma].trim())
}
pub const KNOWN_CRATE_TYPES: &[&str] =
&["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"];

View file

@ -14,51 +14,55 @@ struct CheckCfg {
enum Contains {
Some { contains: &'static [&'static str], doesnt_contain: &'static [&'static str] },
Only(&'static str),
Nothing,
}
fn main() {
check(CheckCfg { args: &[], contains: Contains::Only("any()=any()") });
check(CheckCfg { args: &[], contains: Contains::Nothing });
check(CheckCfg {
args: &["--check-cfg=cfg()"],
contains: Contains::Some {
contains: &["unix", "miri"],
doesnt_contain: &["any()", "any()=any()"],
contains: &["cfg(unix, values(none()))", "cfg(miri, values(none()))"],
doesnt_contain: &["cfg(any())"],
},
});
check(CheckCfg {
args: &["--check-cfg=cfg(any())"],
contains: Contains::Some {
contains: &["any()", "unix", r#"target_feature="crt-static""#],
contains: &["cfg(any())", "cfg(unix, values(none()))"],
doesnt_contain: &["any()=any()"],
},
});
check(CheckCfg {
args: &["--check-cfg=cfg(feature)"],
contains: Contains::Some {
contains: &["unix", "miri", "feature"],
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
contains: &[
"cfg(unix, values(none()))",
"cfg(miri, values(none()))",
"cfg(feature, values(none()))",
],
doesnt_contain: &["cfg(any())", "cfg(feature)"],
},
});
check(CheckCfg {
args: &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#],
contains: Contains::Some {
contains: &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""],
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
contains: &[r#"cfg(feature, values("", "lol", "test", none()))"#],
doesnt_contain: &["cfg(any())", "cfg(feature, values(none()))", "cfg(feature)"],
},
});
check(CheckCfg {
args: &["--check-cfg=cfg(feature, values())"],
contains: Contains::Some {
contains: &["feature="],
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature"],
contains: &["cfg(feature, values())"],
doesnt_contain: &["cfg(any())", "cfg(feature, values(none()))", "cfg(feature)"],
},
});
check(CheckCfg {
args: &["--check-cfg=cfg(feature, values())", "--check-cfg=cfg(feature, values(none()))"],
contains: Contains::Some {
contains: &["feature"],
doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
contains: &["cfg(feature, values(none()))"],
doesnt_contain: &["cfg(any())", "cfg(feature, values())"],
},
});
check(CheckCfg {
@ -67,8 +71,8 @@ fn main() {
r#"--check-cfg=cfg(feature, values("tmp"))"#,
],
contains: Contains::Some {
contains: &["unix", "miri", "feature=any()"],
doesnt_contain: &["any()", "any()=any()", "feature", "feature=", "feature=\"tmp\""],
contains: &["cfg(feature, values(any()))"],
doesnt_contain: &["cfg(any())", r#"cfg(feature, values("tmp"))"#],
},
});
check(CheckCfg {
@ -78,8 +82,12 @@ fn main() {
r#"--check-cfg=cfg(feature, values("tmp"))"#,
],
contains: Contains::Some {
contains: &["has_foo", "has_bar", "feature=\"tmp\""],
doesnt_contain: &["any()", "any()=any()", "feature"],
contains: &[
"cfg(has_foo, values(none()))",
"cfg(has_bar, values(none()))",
r#"cfg(feature, values("tmp"))"#,
],
doesnt_contain: &["cfg(any())", "cfg(feature)"],
},
});
}
@ -94,16 +102,15 @@ fn check(CheckCfg { args, contains }: CheckCfg) {
for l in stdout.lines() {
assert!(l == l.trim());
if let Some((left, right)) = l.split_once('=') {
if right != "any()" && right != "" {
assert!(right.starts_with("\""));
assert!(right.ends_with("\""));
}
assert!(!left.contains("\""));
} else {
assert!(!l.contains("\""));
}
assert!(found.insert(l.to_string()), "{}", &l);
assert!(l.starts_with("cfg("), "{l}");
assert!(l.ends_with(")"), "{l}");
assert_eq!(
l.chars().filter(|c| *c == '(').count(),
l.chars().filter(|c| *c == ')').count(),
"{l}"
);
assert!(l.chars().filter(|c| *c == '"').count() % 2 == 0, "{l}");
assert!(found.insert(l.to_string()), "{l}");
}
match contains {
@ -131,9 +138,8 @@ fn check(CheckCfg { args, contains }: CheckCfg) {
);
}
}
Contains::Only(only) => {
assert!(found.contains(&only.to_string()), "{:?} != {:?}", &only, &found);
assert!(found.len() == 1, "len: {}, instead of 1", found.len());
Contains::Nothing => {
assert!(found.len() == 0, "len: {}, instead of 0", found.len());
}
}
}

View file

@ -250,7 +250,7 @@ set-window-size: (1100, 600)
reload:
assert-count: ("//*[@class='tooltip popover']", 0)
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
assert-count: ("//*[@class='tooltip popover']", 1)
wait-for-count: ("//*[@class='tooltip popover']", 1)
call-function: ("open-settings-menu", {})
assert-count: ("//*[@class='tooltip popover']", 0)
wait-for-count: ("//*[@class='tooltip popover']", 0)
assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"

View file

@ -88,7 +88,7 @@ note: required for `str` to implement `Foo<'_, '_, u8>`
LL | impl<'a, 'b, T, S> Foo<'a, 'b, S> for T {}
| - ^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
error: aborting due to 5 previous errors

View file

@ -88,7 +88,7 @@ note: required for `str` to implement `Foo<'?0, '?1, u8>`
LL | impl<'a, 'b, T, S> Foo<'a, 'b, S> for T {}
| - ^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
error: aborting due to 5 previous errors

View file

@ -0,0 +1,21 @@
//! regression test for <https://github.com/rust-lang/rust/issues/151024>
#![feature(min_generic_const_args)]
#![feature(adt_const_params)]
#![expect(incomplete_features)]
trait Trait1<const N: usize> {}
trait Trait2<const N: [u8; 3]> {}
fn foo<T>()
where
T: Trait1<{ [] }>, //~ ERROR: expected `usize`, found const array
{
}
fn bar<T>()
where
T: Trait2<3>, //~ ERROR: mismatched types
{
}
fn main() {}

View file

@ -0,0 +1,15 @@
error: expected `usize`, found const array
--> $DIR/array-expr-type-mismatch-in-where-bound.rs:11:17
|
LL | T: Trait1<{ [] }>,
| ^^
error[E0308]: mismatched types
--> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15
|
LL | T: Trait2<3>,
| ^ expected `[u8; 3]`, found integer
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,13 @@
//@ check-fail
// Check that type parameters on EIIs are properly rejected.
// Specifically a regression test for https://github.com/rust-lang/rust/issues/149983.
#![feature(extern_item_impls)]
#[eii]
fn foo();
#[foo]
fn foo_impl<T>() {}
//~^ ERROR `foo_impl` cannot have generic parameters other than lifetimes
fn main() {}

View file

@ -0,0 +1,12 @@
error: `foo_impl` cannot have generic parameters other than lifetimes
--> $DIR/generic_implementation.rs:10:1
|
LL | #[foo]
| ------ required by this attribute
LL | fn foo_impl<T>() {}
| ^^^^^^^^^^^^^^^^
|
= help: `#[foo]` marks the implementation of an "externally implementable item"
error: aborting due to 1 previous error

View file

@ -0,0 +1,10 @@
//@ check-fail
// Check that type parameters on EIIs are properly rejected.
// Specifically a regression test for https://github.com/rust-lang/rust/issues/149983.
#![feature(extern_item_impls)]
#[eii]
fn foo<T>() {}
//~^ ERROR externally implementable items may not have type parameters
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0044]: externally implementable items may not have type parameters
--> $DIR/type_params_149983.rs:7:1
|
LL | fn foo<T>() {}
| ^^^^^^^^^^^ can't have type parameters
|
= help: replace the type parameters with concrete types like `u32`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0044`.

View file

@ -0,0 +1,50 @@
use std::fmt::Display;
trait ImplicitTrait {
fn foo(&self);
}
trait ExplicitTrait {
fn foo(&self);
}
trait DisplayTrait {
fn foo(&self);
}
trait UnimplementedTrait {
fn foo(&self);
}
// Implicitly requires `T: Sized`.
impl<T> ImplicitTrait for T {
fn foo(&self) {}
}
// Explicitly requires `T: Sized`.
impl<T: Sized> ExplicitTrait for T {
fn foo(&self) {}
}
// Requires `T: Display`.
impl<T: Display> DisplayTrait for T {
fn foo(&self) {}
}
fn main() {
// `[u8]` does not implement `Sized`.
let x: &[u8] = &[];
ImplicitTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: ImplicitTrait` is not satisfied [E0277]
ExplicitTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: ExplicitTrait` is not satisfied [E0277]
// `UnimplementedTrait` has no implementations.
UnimplementedTrait::foo(x);
//~^ ERROR: the trait bound `[u8]: UnimplementedTrait` is not satisfied [E0277]
// `[u8; 0]` implements `Sized` but not `Display`.
let x: &[u8; 0] = &[];
DisplayTrait::foo(x);
//~^ ERROR: the trait bound `[u8; 0]: DisplayTrait` is not satisfied [E0277]
}

View file

@ -0,0 +1,77 @@
error[E0277]: the trait bound `[u8]: ImplicitTrait` is not satisfied
--> $DIR/E0277-4.rs:37:24
|
LL | ImplicitTrait::foo(x);
| ------------------ ^ the trait `Sized` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
note: required for `[u8]` to implement `ImplicitTrait`
--> $DIR/E0277-4.rs:20:9
|
LL | impl<T> ImplicitTrait for T {
| - ^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider borrowing here
|
LL | ImplicitTrait::foo(&x);
| +
LL | ImplicitTrait::foo(&mut x);
| ++++
error[E0277]: the trait bound `[u8]: ExplicitTrait` is not satisfied
--> $DIR/E0277-4.rs:39:24
|
LL | ExplicitTrait::foo(x);
| ------------------ ^ the trait `Sized` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
note: required for `[u8]` to implement `ExplicitTrait`
--> $DIR/E0277-4.rs:25:16
|
LL | impl<T: Sized> ExplicitTrait for T {
| ----- ^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
help: consider borrowing here
|
LL | ExplicitTrait::foo(&x);
| +
LL | ExplicitTrait::foo(&mut x);
| ++++
error[E0277]: the trait bound `[u8]: UnimplementedTrait` is not satisfied
--> $DIR/E0277-4.rs:43:29
|
LL | UnimplementedTrait::foo(x);
| ----------------------- ^ the trait `UnimplementedTrait` is not implemented for `[u8]`
| |
| required by a bound introduced by this call
|
help: this trait has no implementations, consider adding one
--> $DIR/E0277-4.rs:15:1
|
LL | trait UnimplementedTrait {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `[u8; 0]: DisplayTrait` is not satisfied
--> $DIR/E0277-4.rs:48:23
|
LL | DisplayTrait::foo(x);
| ----------------- ^ the trait `std::fmt::Display` is not implemented for `[u8; 0]`
| |
| required by a bound introduced by this call
|
note: required for `[u8; 0]` to implement `DisplayTrait`
--> $DIR/E0277-4.rs:30:18
|
LL | impl<T: Display> DisplayTrait for T {
| ------- ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -11,7 +11,7 @@ note: required for `GetNext<<<<... as Next>::Next as Next>::Next as Next>::Next>
LL | impl<T: Next> Next for GetNext<T> {
| - ^^^^ ^^^^^^^^^^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
= note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-23122-2.long-type-$LONG_TYPE_HASH.txt'
= note: consider using `--verbose` to print the full type name to the console

View file

@ -22,9 +22,12 @@ struct Unsized {
fn main() {
println!("{:#?}", const { Type::of::<(u8, u8, ())>() }.kind);
println!("{:#?}", const { Type::of::<[u8; 2]>() }.kind);
println!("{:#?}", const { Type::of::<Foo>() }.kind);
println!("{:#?}", const { Type::of::<Bar>() }.kind);
println!("{:#?}", const { Type::of::<&Unsized>() }.kind);
println!("{:#?}", const { Type::of::<&str>() }.kind);
println!("{:#?}", const { Type::of::<&[u8]>() }.kind);
println!("{:#?}", const { Type::of::<str>() }.kind);
println!("{:#?}", const { Type::of::<[u8]>() }.kind);
}

View file

@ -16,6 +16,14 @@ Tuple(
],
},
)
Array(
Array {
element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
len: 2,
},
)
Other
Other
Other
Other
Other

View file

@ -1,36 +0,0 @@
#![feature(type_info)]
//@ run-pass
use std::mem::type_info::{Type, TypeKind};
fn assert_tuple_arity<T: 'static, const N: usize>() {
const {
match &Type::of::<T>().kind {
TypeKind::Tuple(tup) => {
assert!(tup.fields.len() == N);
}
_ => unreachable!(),
}
}
}
fn main() {
assert_tuple_arity::<(), 0>();
assert_tuple_arity::<(u8,), 1>();
assert_tuple_arity::<(u8, u8), 2>();
const {
match &Type::of::<(u8, u8)>().kind {
TypeKind::Tuple(tup) => {
let [a, b] = tup.fields else { unreachable!() };
assert!(a.offset == 0);
assert!(b.offset == 1);
match (&a.ty.info().kind, &b.ty.info().kind) {
(TypeKind::Leaf, TypeKind::Leaf) => {}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
}

View file

@ -0,0 +1,20 @@
//@ edition: 2024
#![feature(decl_macro)]
// Regression test for issue <https://github.com/rust-lang/rust/issues/150711>
// The compiler previously ICE'd during identifier resolution
// involving `macro` items and `use` inside a public macro.
mod foo {
macro f() {}
pub macro m() {
use f; //~ ERROR `f` is private, and cannot be re-exported
f!(); //~ ERROR macro import `f` is private
}
}
fn main() {
foo::m!();
}

View file

@ -0,0 +1,47 @@
error[E0364]: `f` is private, and cannot be re-exported
--> $DIR/decl-macro-use-no-ice.rs:13:13
|
LL | use f;
| ^
...
LL | foo::m!();
| --------- in this macro invocation
|
note: consider marking `f` as `pub` in the imported module
--> $DIR/decl-macro-use-no-ice.rs:13:13
|
LL | use f;
| ^
...
LL | foo::m!();
| --------- in this macro invocation
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0603]: macro import `f` is private
--> $DIR/decl-macro-use-no-ice.rs:14:9
|
LL | f!();
| ^ private macro import
...
LL | foo::m!();
| --------- in this macro invocation
|
note: the macro import `f` is defined here...
--> $DIR/decl-macro-use-no-ice.rs:13:13
|
LL | use f;
| ^
...
LL | foo::m!();
| --------- in this macro invocation
note: ...and refers to the macro `f` which is defined here
--> $DIR/decl-macro-use-no-ice.rs:10:5
|
LL | macro f() {}
| ^^^^^^^^^
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0364, E0603.
For more information about an error, try `rustc --explain E0364`.

View file

@ -17,11 +17,10 @@ error[E0277]: `[i32]` is not an iterator
--> $DIR/slice-issue-87994.rs:3:12
|
LL | for _ in v[1..] {
| ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
| ^^^^^^ the trait `Sized` is not implemented for `[i32]`
|
= note: the trait bound `[i32]: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `[i32]` to implement `IntoIterator`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider borrowing here
|
LL | for _ in &v[1..] {
@ -48,11 +47,10 @@ error[E0277]: `[K]` is not an iterator
--> $DIR/slice-issue-87994.rs:11:13
|
LL | for i2 in v2[1..] {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
| ^^^^^^^ the trait `Sized` is not implemented for `[K]`
|
= note: the trait bound `[K]: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `[K]` to implement `IntoIterator`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider borrowing here
|
LL | for i2 in &v2[1..] {

View file

@ -2,9 +2,9 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/dyn-iterator-deref-in-for-loop.rs:9:17
|
LL | for item in *things {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| ^^^^^^^ the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|

View file

@ -2,9 +2,9 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/dyn-iterator-deref-in-for-loop.rs:9:17
|
LL | for item in *things {
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| ^^^^^^^ the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: the trait bound `Sized` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|

View file

@ -11,7 +11,7 @@ note: required for `{integer}` to implement `Set<&[_]>`
LL | impl<'a, T, S> Set<&'a [T]> for S where
| - ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
| unsatisfied trait bound implicitly introduced here
= note: 128 redundant requirements hidden
= note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>`

View file

@ -332,6 +332,14 @@ trigger_labels = [
"A-type-based-search",
]
[autolabel."A-rustdoc-js"]
trigger_files = [
"src/librustdoc/html/static/js/",
"src/librustdoc/html/static/css/",
"tests/rustdoc-js/",
"tests/rustdoc-js-std/",
]
[autolabel."T-compiler"]
trigger_files = [
# Source code