Auto merge of #152574 - JonathanBrouwer:rollup-ERc05AE, r=JonathanBrouwer

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#152323 (Fix ICE in borrowck when recovering `fn_sig` for `-> _`)
 - rust-lang/rust#152469 (Remove unused features)
 - rust-lang/rust#152515 (Extract `DepKindVTable` constructors to their own module)
 - rust-lang/rust#152555 (Port `#[rustc_diagnostic_item]` to the new attribute parsers)
 - rust-lang/rust#152218 (Report unconstrained region in hidden types lazily)
 - rust-lang/rust#152356 (Improve the `inline_fluent!` macro)
 - rust-lang/rust#152392 (Fix ICE in supertrait_vtable_slot when supertrait has missing generics)
 - rust-lang/rust#152407 (Add regression test for type_const with unit struct ctor under mGCA)
 - rust-lang/rust#152440 (Fix typos and grammar in compiler and build documentation)
 - rust-lang/rust#152536 (bootstrap: add explicit UTF-8 encoding to text-mode open() calls)
 - rust-lang/rust#152554 (Remove `deprecated_safe` and its corresponding feature gate)
 - rust-lang/rust#152556 (doc: move riscv64a23-unknown-linux-gnu to tier 2)
 - rust-lang/rust#152563 (Replace "bug" with "issue" in triagebot ping messages)
 - rust-lang/rust#152565 (fix missleading error for tuple ctor)

Failed merges:

 - rust-lang/rust#152512 (core: Implement feature `float_exact_integer_constants`)
 - rust-lang/rust#152296 (Port `rust_nonnull_optimization_guaranteed` and `rustc_do_not_const_check` to the new attribute parser)
This commit is contained in:
bors 2026-02-13 23:16:29 +00:00
commit f403dee04e
103 changed files with 1086 additions and 652 deletions

View file

@ -1,5 +1,5 @@
// tidy-alphabetical-start
#![cfg_attr(all(feature = "nightly", bootstrap), feature(assert_matches))]
#![cfg_attr(all(feature = "nightly", bootstrap, test), feature(assert_matches))]
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
#![cfg_attr(feature = "nightly", feature(step_trait))]

View file

@ -1103,6 +1103,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
}
pub(crate) struct RustcDiagnosticItemParser;
impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Trait),
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::MacroDef),
Allow(Target::TyAlias),
Allow(Target::AssocTy),
Allow(Target::AssocConst),
Allow(Target::Fn),
Allow(Target::Const),
Allow(Target::Mod),
Allow(Target::Impl { of_trait: false }),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: false })),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::Crate),
]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
let Some(value) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};
Some(AttributeKind::RustcDiagnosticItem(value))
}
}
pub(crate) struct RustcSymbolName;
impl<S: Stage> SingleAttributeParser<S> for RustcSymbolName {

View file

@ -203,6 +203,7 @@ attribute_parsers!(
Single<RustcBuiltinMacroParser>,
Single<RustcDefPath>,
Single<RustcDeprecatedSafe2024Parser>,
Single<RustcDiagnosticItemParser>,
Single<RustcForceInlineParser>,
Single<RustcIfThisChangedParser>,
Single<RustcLayoutScalarValidRangeEndParser>,

View file

@ -24,13 +24,13 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use tracing::{debug, instrument};
use super::reverse_sccs::ReverseSccGraph;
use crate::BorrowckInferCtxt;
use crate::consumers::RegionInferenceContext;
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
use crate::type_check::canonical::fully_perform_op_raw;
use crate::type_check::free_region_relations::UniversalRegionRelations;
use crate::type_check::{Locations, MirTypeckRegionConstraints};
use crate::universal_regions::{RegionClassification, UniversalRegions};
use crate::{BorrowckInferCtxt, CollectRegionConstraintsResult};
mod member_constraints;
mod region_ctxt;
@ -126,6 +126,31 @@ fn nll_var_to_universal_region<'tcx>(
}
}
/// Record info needed to report the same name error later.
#[derive(Copy, Clone, Debug)]
pub(crate) struct UnexpectedHiddenRegion<'tcx> {
// The def_id of the body where this error occurs.
// Needed to handle region vars with their corresponding `infcx`.
def_id: LocalDefId,
opaque_type_key: OpaqueTypeKey<'tcx>,
hidden_type: ProvisionalHiddenType<'tcx>,
member_region: Region<'tcx>,
}
impl<'tcx> UnexpectedHiddenRegion<'tcx> {
pub(crate) fn to_error(self) -> (LocalDefId, DeferredOpaqueTypeError<'tcx>) {
let UnexpectedHiddenRegion { def_id, opaque_type_key, hidden_type, member_region } = self;
(
def_id,
DeferredOpaqueTypeError::UnexpectedHiddenRegion {
opaque_type_key,
hidden_type,
member_region,
},
)
}
}
/// Collect all defining uses of opaque types inside of this typeck root. This
/// expects the hidden type to be mapped to the definition parameters of the opaque
/// and errors if we end up with distinct hidden types.
@ -176,11 +201,13 @@ struct DefiningUse<'tcx> {
/// It also means that this whole function is not really soundness critical as we
/// recheck all uses of the opaques regardless.
pub(crate) fn compute_definition_site_hidden_types<'tcx>(
def_id: LocalDefId,
infcx: &BorrowckInferCtxt<'tcx>,
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
constraints: &MirTypeckRegionConstraints<'tcx>,
location_map: Rc<DenseLocationMap>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
let mut errors = Vec::new();
@ -204,8 +231,10 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>(
// up equal to one of their choice regions and compute the actual hidden type of
// the opaque type definition. This is stored in the `root_cx`.
compute_definition_site_hidden_types_from_defining_uses(
def_id,
&rcx,
hidden_types,
unconstrained_hidden_type_errors,
&defining_uses,
&mut errors,
);
@ -274,8 +303,10 @@ fn collect_defining_uses<'tcx>(
#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]
fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
def_id: LocalDefId,
rcx: &RegionCtxt<'_, 'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
defining_uses: &[DefiningUse<'tcx>],
errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
) {
@ -293,16 +324,29 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
Ok(hidden_type) => hidden_type,
Err(r) => {
debug!("UnexpectedHiddenRegion: {:?}", r);
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
hidden_type,
opaque_type_key,
member_region: ty::Region::new_var(tcx, r),
});
let guar = tcx.dcx().span_delayed_bug(
hidden_type.span,
"opaque type with non-universal region args",
);
ty::ProvisionalHiddenType::new_error(tcx, guar)
// If we're using the next solver, the unconstrained region may be resolved by a
// fully defining use from another body.
// So we don't generate error eagerly here.
if rcx.infcx.tcx.use_typing_mode_borrowck() {
unconstrained_hidden_type_errors.push(UnexpectedHiddenRegion {
def_id,
hidden_type,
opaque_type_key,
member_region: ty::Region::new_var(tcx, r),
});
continue;
} else {
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
hidden_type,
opaque_type_key,
member_region: ty::Region::new_var(tcx, r),
});
let guar = tcx.dcx().span_delayed_bug(
hidden_type.span,
"opaque type with non-universal region args",
);
ty::ProvisionalHiddenType::new_error(tcx, guar)
}
}
};
@ -570,6 +614,40 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
errors
}
/// We handle `UnexpectedHiddenRegion` error lazily in the next solver as
/// there may be a fully defining use in another body.
///
/// In case such a defining use does not exist, we register an error here.
pub(crate) fn handle_unconstrained_hidden_type_errors<'tcx>(
tcx: TyCtxt<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
collect_region_constraints_results: &mut FxIndexMap<
LocalDefId,
CollectRegionConstraintsResult<'tcx>,
>,
) {
let mut unconstrained_hidden_type_errors = std::mem::take(unconstrained_hidden_type_errors);
unconstrained_hidden_type_errors
.retain(|unconstrained| !hidden_types.contains_key(&unconstrained.opaque_type_key.def_id));
unconstrained_hidden_type_errors.iter().for_each(|t| {
tcx.dcx()
.span_delayed_bug(t.hidden_type.span, "opaque type with non-universal region args");
});
// `UnexpectedHiddenRegion` error contains region var which only makes sense in the
// corresponding `infcx`.
// So we need to insert the error to the body where it originates from.
for error in unconstrained_hidden_type_errors {
let (def_id, error) = error.to_error();
let Some(result) = collect_region_constraints_results.get_mut(&def_id) else {
unreachable!("the body should depend on opaques type if it has opaque use");
};
result.deferred_opaque_type_errors.push(error);
}
}
/// In theory `apply_definition_site_hidden_types` could introduce new uses of opaque types.
/// We do not check these new uses so this could be unsound.
///

View file

@ -12,8 +12,9 @@ use smallvec::SmallVec;
use crate::consumers::BorrowckConsumer;
use crate::nll::compute_closure_requirements_modulo_opaques;
use crate::region_infer::opaque_types::{
apply_definition_site_hidden_types, clone_and_resolve_opaque_types,
UnexpectedHiddenRegion, apply_definition_site_hidden_types, clone_and_resolve_opaque_types,
compute_definition_site_hidden_types, detect_opaque_types_added_while_handling_opaque_types,
handle_unconstrained_hidden_type_errors,
};
use crate::type_check::{Locations, constraint_conversion};
use crate::{
@ -26,7 +27,12 @@ use crate::{
pub(super) struct BorrowCheckRootCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
root_def_id: LocalDefId,
/// This contains fully resolved hidden types or `ty::Error`.
hidden_types: FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
/// This contains unconstrained regions in hidden types.
/// Only used for deferred error reporting. See
/// [`crate::region_infer::opaque_types::handle_unconstrained_hidden_type_errors`]
unconstrained_hidden_type_errors: Vec<UnexpectedHiddenRegion<'tcx>>,
/// The region constraints computed by [borrowck_collect_region_constraints]. This uses
/// an [FxIndexMap] to guarantee that iterating over it visits nested bodies before
/// their parents.
@ -49,6 +55,7 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
tcx,
root_def_id,
hidden_types: Default::default(),
unconstrained_hidden_type_errors: Default::default(),
collect_region_constraints_results: Default::default(),
propagated_borrowck_results: Default::default(),
tainted_by_errors: None,
@ -84,23 +91,32 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
fn handle_opaque_type_uses(&mut self) {
let mut per_body_info = Vec::new();
for input in self.collect_region_constraints_results.values_mut() {
for (def_id, input) in &mut self.collect_region_constraints_results {
let (num_entries, opaque_types) = clone_and_resolve_opaque_types(
&input.infcx,
&input.universal_region_relations,
&mut input.constraints,
);
input.deferred_opaque_type_errors = compute_definition_site_hidden_types(
*def_id,
&input.infcx,
&input.universal_region_relations,
&input.constraints,
Rc::clone(&input.location_map),
&mut self.hidden_types,
&mut self.unconstrained_hidden_type_errors,
&opaque_types,
);
per_body_info.push((num_entries, opaque_types));
}
handle_unconstrained_hidden_type_errors(
self.tcx,
&mut self.hidden_types,
&mut self.unconstrained_hidden_type_errors,
&mut self.collect_region_constraints_results,
);
for (input, (opaque_types_storage_num_entries, opaque_types)) in
self.collect_region_constraints_results.values_mut().zip(per_body_info)
{

View file

@ -2,8 +2,8 @@
// Note: please avoid adding other feature gates where possible
#![feature(rustc_private)]
// Only used to define intrinsics in `compiler_builtins.rs`.
#![feature(f16)]
#![feature(f128)]
#![cfg_attr(feature = "jit", feature(f16))]
#![cfg_attr(feature = "jit", feature(f128))]
// Note: please avoid adding other feature gates where possible
#![warn(rust_2018_idioms)]
#![warn(unreachable_pub)]

View file

@ -16,7 +16,7 @@ module to generate correct metadata and insert it into the LLVM IR.
As the exact format of metadata trees may change between different LLVM
versions, we now use LLVM
[DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
to create metadata where possible. This will hopefully ease the adaption of
to create metadata where possible. This will hopefully ease the adaptation of
this module to future LLVM versions.
The public API of the module is a set of functions that will insert the
@ -87,19 +87,19 @@ describe the type anew. This behavior is encapsulated in the
## Source Locations and Line Information
In addition to data type descriptions the debugging information must also
allow to map machine code locations back to source code locations in order
allow mapping machine code locations back to source code locations in order
to be useful. This functionality is also handled in this module. The
following functions allow to control source mappings:
following functions allow controlling source mappings:
+ `set_source_location()`
+ `clear_source_location()`
+ `start_emitting_source_locations()`
`set_source_location()` allows to set the current source location. All IR
`set_source_location()` allows setting the current source location. All IR
instructions created after a call to this function will be linked to the
given source location, until another location is specified with
`set_source_location()` or the source location is cleared with
`clear_source_location()`. In the later case, subsequent IR instruction
`clear_source_location()`. In the latter case, subsequent IR instructions
will not be linked to any source location. As you can see, this is a
stateful API (mimicking the one in LLVM), so be careful with source
locations set by previous calls. It's probably best to not rely on any

View file

@ -471,9 +471,9 @@ fn report_eval_error<'tcx>(
span,
inline_fluent!(
"evaluation of `{$instance}` failed {$num_frames ->
[0] here
*[other] inside this call
}"
[0] here
*[other] inside this call
}"
),
);
for frame in frames {

View file

@ -491,10 +491,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
Err(err) => throw_ub_custom!(
inline_fluent!(
"invalid align passed to `{$name}`: {$align} is {$err_kind ->
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"
),
name = "const_allocate",
err_kind = err.diag_ident(),
@ -521,10 +521,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
Err(err) => throw_ub_custom!(
inline_fluent!(
"invalid align passed to `{$name}`: {$align} is {$err_kind ->
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"
),
name = "const_deallocate",
err_kind = err.diag_ident(),

View file

@ -393,16 +393,17 @@ impl Subdiagnostic for FrameNote {
}
let msg = diag.eagerly_translate(inline_fluent!(
r#"{$times ->
[0] {const_eval_frame_note_inner}
*[other] [... {$times} additional calls {const_eval_frame_note_inner} ...]
}
const_eval_frame_note_inner = inside {$where_ ->
[closure] closure
[instance] `{$instance}`
*[other] {""}
}
"#
[0] inside {$where_ ->
[closure] closure
[instance] `{$instance}`
*[other] {""}
}
*[other] [... {$times} additional calls inside {$where_ ->
[closure] closure
[instance] `{$instance}`
*[other] {""}
} ...]
}"#
));
diag.remove_arg("times");
diag.remove_arg("where_");
@ -663,89 +664,96 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
InvalidMeta(InvalidMetaKind::SliceTooBig) => "invalid metadata in wide pointer: slice is bigger than largest supported object".into(),
InvalidMeta(InvalidMetaKind::TooBig) => "invalid metadata in wide pointer: total size is bigger than largest supported object".into(),
UnterminatedCString(_) => "reading a null-terminated string starting at {$pointer} with no null found before end of allocation".into(),
PointerUseAfterFree(_, _) => inline_fluent!("{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$alloc_id} has been freed, so this pointer is dangling"),
PointerOutOfBounds { .. } => inline_fluent!("{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got {$pointer} which {$ptr_offset_is_neg ->
[true] points to before the beginning of the allocation
*[false] {$inbounds_size_is_neg ->
[false] {$alloc_size_minus_ptr_offset ->
[0] is at or beyond the end of the allocation of size {$alloc_size ->
[1] 1 byte
*[x] {$alloc_size} bytes
}
[1] is only 1 byte from the end of the allocation
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
}
*[true] {$ptr_offset_abs ->
[0] is at the beginning of the allocation
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
}
}
}
"),
DanglingIntPointer { addr: 0, .. } => inline_fluent!("{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got null pointer"),
DanglingIntPointer { .. } => inline_fluent!("{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got {$pointer} which is a dangling pointer (it has no provenance)"),
AlignmentCheckFailed { .. } => inline_fluent!("{$msg ->
[AccessedPtr] accessing memory
*[other] accessing memory based on pointer
} with alignment {$has}, but alignment {$required} is required"),
PointerUseAfterFree(_, _) => inline_fluent!(
"{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$alloc_id} has been freed, so this pointer is dangling"
),
PointerOutOfBounds { .. } => inline_fluent!(
"{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got {$pointer} which {$ptr_offset_is_neg ->
[true] points to before the beginning of the allocation
*[false] {$inbounds_size_is_neg ->
[false] {$alloc_size_minus_ptr_offset ->
[0] is at or beyond the end of the allocation of size {$alloc_size ->
[1] 1 byte
*[x] {$alloc_size} bytes
}
[1] is only 1 byte from the end of the allocation
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
}
*[true] {$ptr_offset_abs ->
[0] is at the beginning of the allocation
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
}
}
}"
),
DanglingIntPointer { addr: 0, .. } => inline_fluent!(
"{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got null pointer"),
DanglingIntPointer { .. } => inline_fluent!(
"{$operation ->
[MemoryAccess] memory access failed
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
*[Dereferenceable] pointer not dereferenceable
}: {$operation ->
[MemoryAccess] attempting to access {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
[1] 1 byte
*[x] {$inbounds_size} bytes
}
*[Dereferenceable] pointer must {$inbounds_size ->
[0] point to some allocation
[1] be dereferenceable for 1 byte
*[x] be dereferenceable for {$inbounds_size} bytes
}
}, but got {$pointer} which is a dangling pointer (it has no provenance)"),
AlignmentCheckFailed { .. } => inline_fluent!(
"{$msg ->
[AccessedPtr] accessing memory
*[other] accessing memory based on pointer
} with alignment {$has}, but alignment {$required} is required"
),
WriteToReadOnly(_) => inline_fluent!("writing to {$allocation} which is read-only"),
DerefFunctionPointer(_) => inline_fluent!("accessing {$allocation} which contains a function"),
DerefVTablePointer(_) => inline_fluent!("accessing {$allocation} which contains a vtable"),
@ -936,9 +944,9 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
NullFnPtr { .. } => {
inline_fluent!(
"{$front_matter}: encountered a {$maybe ->
[true] maybe-null
*[false] null
} function pointer"
[true] maybe-null
*[false] null
} function pointer"
)
}
NeverVal => {
@ -1021,17 +1029,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
NullPtr { ptr_kind: PointerKind::Box, .. } => {
inline_fluent!(
"{$front_matter}: encountered a {$maybe ->
[true] maybe-null
*[false] null
} box"
[true] maybe-null
*[false] null
} box"
)
}
NullPtr { ptr_kind: PointerKind::Ref(_), .. } => {
inline_fluent!(
"{$front_matter}: encountered a {$maybe ->
[true] maybe-null
*[false] null
} reference"
[true] maybe-null
*[false] null
} reference"
)
}
DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {

View file

@ -466,10 +466,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// a < b
if intrinsic_name == sym::ptr_offset_from_unsigned {
throw_ub_custom!(
inline_fluent!("`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr ->
[true] address
*[false] offset
} than second: {$a_offset} < {$b_offset}"),
inline_fluent!(
"`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr ->
[true] address
*[false] offset
} than second: {$a_offset} < {$b_offset}"
),
a_offset = a_offset,
b_offset = b_offset,
is_addr = is_addr,

View file

@ -293,10 +293,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
throw_ub_custom!(
inline_fluent!(
"{$kind ->
[dealloc] deallocating
[realloc] reallocating
*[other] {\"\"}
} {$ptr} which does not point to the beginning of an object"
[dealloc] deallocating
[realloc] reallocating
*[other] {\"\"}
} {$ptr} which does not point to the beginning of an object"
),
ptr = format!("{ptr:?}"),
kind = "realloc"
@ -379,10 +379,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
throw_ub_custom!(
inline_fluent!(
"{$kind ->
[dealloc] deallocating
[realloc] reallocating
*[other] {\"\"}
} {$ptr} which does not point to the beginning of an object"
[dealloc] deallocating
[realloc] reallocating
*[other] {\"\"}
} {$ptr} which does not point to the beginning of an object"
),
ptr = format!("{ptr:?}"),
kind = "dealloc",
@ -396,11 +396,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
err_ub_custom!(
inline_fluent!(
"deallocating {$alloc_id}, which is {$kind ->
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
),
alloc_id = alloc_id,
kind = "fn",
@ -410,11 +410,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
err_ub_custom!(
inline_fluent!(
"deallocating {$alloc_id}, which is {$kind ->
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
),
alloc_id = alloc_id,
kind = "vtable",
@ -424,11 +424,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
err_ub_custom!(
inline_fluent!(
"deallocating {$alloc_id}, which is {$kind ->
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
),
alloc_id = alloc_id,
kind = "typeid",
@ -438,11 +438,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
err_ub_custom!(
inline_fluent!(
"deallocating {$alloc_id}, which is {$kind ->
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
[fn] a function
[vtable] a vtable
[static_mem] static memory
*[other] {\"\"}
}"
),
alloc_id = alloc_id,
kind = "static_mem"

View file

@ -12,6 +12,7 @@
#![allow(rustc::potential_query_instability)]
#![cfg_attr(bootstrap, feature(assert_matches))]
#![cfg_attr(bootstrap, feature(cold_path))]
#![cfg_attr(test, feature(test))]
#![deny(unsafe_op_in_unsafe_fn)]
#![feature(allocator_api)]
#![feature(ascii_char)]
@ -30,7 +31,6 @@
#![feature(ptr_alignment_type)]
#![feature(rustc_attrs)]
#![feature(sized_hierarchy)]
#![feature(test)]
#![feature(thread_id_value)]
#![feature(trusted_len)]
#![feature(type_alias_impl_trait)]

View file

@ -60,11 +60,13 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
.with_arg("cause", cause)
}
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
Diag::new(dcx, level, inline_fluent!("invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind ->
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"))
Diag::new(dcx, level, inline_fluent!(
"invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind ->
[not_power_of_two] not a power of 2
[too_large] too large
*[other] {\"\"}
}"
))
.with_arg("cause", cause)
.with_arg("err_kind", err.diag_ident())
.with_arg("align", err.align())

View file

@ -14,8 +14,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
// tidy-alphabetical-end
extern crate self as rustc_errors;
@ -63,6 +61,7 @@ pub use rustc_error_messages::{
use rustc_hashes::Hash128;
use rustc_lint_defs::LintExpectationId;
pub use rustc_lint_defs::{Applicability, listify, pluralize};
pub use rustc_macros::inline_fluent;
use rustc_macros::{Decodable, Encodable};
pub use rustc_span::ErrorGuaranteed;
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
@ -1561,7 +1560,7 @@ impl DelayedDiagInner {
let msg = match self.note.status() {
BacktraceStatus::Captured => inline_fluent!(
"delayed at {$emitted_at}
{$note}"
{$note}"
),
// Avoid the needless newline when no backtrace has been captured,
// the display impl should just be a single line.

View file

@ -90,14 +90,3 @@ impl Translator {
}
}
}
/// This macro creates a translatable `DiagMessage` from a literal string.
/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired.
///
/// This is a macro because in the future we may want to globally register these messages.
#[macro_export]
macro_rules! inline_fluent {
($inline: literal) => {
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline))
};
}

View file

@ -919,7 +919,7 @@ impl SyntaxExtension {
fn get_hide_backtrace(attrs: &[hir::Attribute]) -> bool {
// FIXME(estebank): instead of reusing `#[rustc_diagnostic_item]` as a proxy, introduce a
// new attribute purely for this under the `#[diagnostic]` namespace.
ast::attr::find_by_name(attrs, sym::rustc_diagnostic_item).is_some()
find_attr!(attrs, AttributeKind::RustcDiagnosticItem(..))
}
/// Constructs a syntax extension with the given properties

View file

@ -862,13 +862,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
register_tool, CrateLevel, template!(List: &["tool1, tool2, ..."]), DuplicatesOk,
EncodeCrossCrate::No, experimental!(register_tool),
),
// lang-team MCP 147
gated!(
deprecated_safe, Normal, template!(List: &[r#"since = "version", note = "...""#]), ErrorFollowing,
EncodeCrossCrate::Yes, experimental!(deprecated_safe),
),
// `#[cfi_encoding = ""]`
gated!(
cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,

View file

@ -102,6 +102,8 @@ declare_features! (
/// Allows default type parameters to influence type inference.
(removed, default_type_parameter_fallback, "1.82.0", Some(27336),
Some("never properly implemented; requires significant design work"), 127655),
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
(removed, deprecated_safe, "CURRENT_RUSTC_VERSION", Some(94978), Some("never properly implemented, in the way of attribute refactor"), 152554),
/// Allows deriving traits as per `SmartPointer` specification
(removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.

View file

@ -454,8 +454,6 @@ declare_features! (
/// Allows the use of default values on struct definitions and the construction of struct
/// literals with the functional update syntax without a base.
(unstable, default_field_values, "1.85.0", Some(132162)),
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
(unstable, deprecated_safe, "1.61.0", Some(94978)),
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
/// Allows deref patterns.

View file

@ -1156,6 +1156,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_deprecated_safe_2024]`
RustcDeprecatedSafe2024 { suggestion: Symbol },
/// Represents `#[rustc_diagnostic_item]`
RustcDiagnosticItem(Symbol),
/// Represents `#[rustc_dummy]`.
RustcDummy,

View file

@ -113,6 +113,7 @@ impl AttributeKind {
RustcDelayedBugFromInsideQuery => No,
RustcDenyExplicitImpl(..) => No,
RustcDeprecatedSafe2024 { .. } => Yes,
RustcDiagnosticItem(..) => Yes,
RustcDummy => No,
RustcDumpDefParents => No,
RustcDumpItemBounds => No,

View file

@ -1063,6 +1063,70 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
)
}
/// Convert `ReLateParam`s in `value` back into `ReBound`s and bind it with `bound_vars`.
fn late_param_regions_to_bound<'tcx, T>(
tcx: TyCtxt<'tcx>,
scope: DefId,
bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
value: T,
) -> ty::Binder<'tcx, T>
where
T: ty::TypeFoldable<TyCtxt<'tcx>>,
{
let value = fold_regions(tcx, value, |r, debruijn| match r.kind() {
ty::ReLateParam(lp) => {
// Should be in scope, otherwise inconsistency happens somewhere.
assert_eq!(lp.scope, scope);
let br = match lp.kind {
// These variants preserve the bound var index.
kind @ (ty::LateParamRegionKind::Anon(idx)
| ty::LateParamRegionKind::NamedAnon(idx, _)) => {
let idx = idx as usize;
let var = ty::BoundVar::from_usize(idx);
let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied()
else {
bug!("unexpected late-bound region {kind:?} for bound vars {bound_vars:?}");
};
ty::BoundRegion { var, kind }
}
// For named regions, look up the corresponding bound var.
ty::LateParamRegionKind::Named(def_id) => bound_vars
.iter()
.enumerate()
.find_map(|(idx, bv)| match bv {
ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did))
if did == def_id =>
{
Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
}
_ => None,
})
.unwrap(),
ty::LateParamRegionKind::ClosureEnv => bound_vars
.iter()
.enumerate()
.find_map(|(idx, bv)| match bv {
ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => {
Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
}
_ => None,
})
.unwrap(),
};
ty::Region::new_bound(tcx, debruijn, br)
}
_ => r,
});
ty::Binder::bind_with_vars(value, bound_vars)
}
fn recover_infer_ret_ty<'tcx>(
icx: &ItemCtxt<'tcx>,
infer_ret_ty: &'tcx hir::Ty<'tcx>,
@ -1138,13 +1202,22 @@ fn recover_infer_ret_ty<'tcx>(
);
}
let guar = diag.emit();
ty::Binder::dummy(tcx.mk_fn_sig(
// If we return a dummy binder here, we can ICE later in borrowck when it encounters
// `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the
// signature binder. See #135845.
let bound_vars = tcx.late_bound_vars(hir_id);
let scope = def_id.to_def_id();
let fn_sig = tcx.mk_fn_sig(
fn_sig.inputs().iter().copied(),
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
fn_sig.c_variadic,
fn_sig.safety,
fn_sig.abi,
))
);
late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
}
pub fn suggest_impl_trait<'tcx>(

View file

@ -2465,7 +2465,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let parent_did = tcx.parent(*def_id);
(tcx.adt_def(parent_did), fn_args, parent_did)
}
_ => return non_adt_or_variant_res(),
_ => {
let e = self.dcx().span_err(
span,
"complex const arguments must be placed inside of a `const` block",
);
return Const::new_error(tcx, e);
}
};
let variant_def = adt_def.variant_with_id(variant_did);

View file

@ -1,6 +1,7 @@
// tidy-alphabetical-start
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
#![cfg_attr(all(feature = "nightly", test), feature(test))]
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait))]
#![cfg_attr(feature = "nightly", feature(new_range_api))]
// tidy-alphabetical-end

View file

@ -446,7 +446,7 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
"specifically, {$num_captured ->
[one] this lifetime is
*[other] these lifetimes are
} in scope but not mentioned in the type's bounds"
} in scope but not mentioned in the type's bounds"
),
)
.note(inline_fluent!(

View file

@ -353,8 +353,10 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> {
self.label,
inline_fluent!("will not be checked at usage sites of the type alias"),
);
diag.note(inline_fluent!("this is a known limitation of the type checker that may be lifted in a future edition.
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information"));
diag.note(inline_fluent!(
"this is a known limitation of the type checker that may be lifted in a future edition.
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information"
));
if self.enable_feat_help {
diag.help(inline_fluent!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics"));
}
@ -1748,10 +1750,12 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
if doctest {
diag.help(inline_fluent!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#));
} else {
diag.help(inline_fluent!("remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth ->
[one] `{$body_name}`
*[other] `{$body_name}` and up {$depth} bodies
}"));
diag.help(inline_fluent!(
"remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth ->
[one] `{$body_name}`
*[other] `{$body_name}` and up {$depth} bodies
}"
));
}
diag.note(inline_fluent!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute"));

View file

@ -196,10 +196,12 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if let Some((open, close, del)) = find_delimiters(cx, span) {
lint.arg("already_suggested", suggest_display || suggest_debug);
lint.multipart_suggestion(
inline_fluent!("{$already_suggested ->
[true] or use
*[false] use
} std::panic::panic_any instead"),
inline_fluent!(
"{$already_suggested ->
[true] or use
*[false] use
} std::panic::panic_any instead"
),
if del == '(' {
vec![(span.until(open), "std::panic::panic_any".into())]
} else {

View file

@ -0,0 +1,10 @@
use syn::{LitStr, parse_macro_input};
use crate::diagnostics::message::Message;
pub(crate) fn inline_fluent(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let inline = parse_macro_input!(input as LitStr);
let message =
Message { attr_span: inline.span(), message_span: inline.span(), value: inline.value() };
message.diag_message(None).into()
}

View file

@ -1,11 +1,13 @@
mod diagnostic;
mod diagnostic_builder;
mod error;
mod inline_fluent;
mod message;
mod subdiagnostic;
mod utils;
use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
pub(super) use inline_fluent::inline_fluent;
use proc_macro2::TokenStream;
use subdiagnostic::SubdiagnosticDerive;
use synstructure::Structure;

View file

@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(rustc::default_hash_types)]
#![feature(if_let_guard)]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_tracked_env)]
@ -241,6 +240,15 @@ decl_derive!(
applicability)] => diagnostics::subdiagnostic_derive
);
/// This macro creates a translatable `DiagMessage` from a fluent format string.
/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired.
///
/// This macro statically checks that the message is valid Fluent, but not that variables in the Fluent message actually exist.
#[proc_macro]
pub fn inline_fluent(input: TokenStream) -> TokenStream {
diagnostics::inline_fluent(input)
}
decl_derive! {
[PrintAttribute] =>
/// Derives `PrintAttribute` for `AttributeKind`.

View file

@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![feature(decl_macro)]
#![feature(error_iter)]
#![feature(file_buffered)]
#![feature(gen_blocks)]

View file

@ -28,6 +28,7 @@
#![allow(internal_features)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![cfg_attr(bootstrap, feature(assert_matches))]
#![cfg_attr(doc, feature(intra_doc_pointers))]
#![feature(allocator_api)]
#![feature(associated_type_defaults)]
#![feature(box_as_ptr)]
@ -43,7 +44,6 @@
#![feature(file_buffered)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
@ -56,7 +56,6 @@
#![feature(try_trait_v2_residual)]
#![feature(try_trait_v2_yeet)]
#![feature(type_alias_impl_trait)]
#![feature(unwrap_infallible)]
#![feature(yeet_expr)]
#![recursion_limit = "256"]
// tidy-alphabetical-end

View file

@ -128,19 +128,25 @@ pub struct Deprecated {
impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
diag.primary_message(match &self.since_kind {
DeprecatedSinceKind::InEffect => inline_fluent!("use of deprecated {$kind} `{$path}`{$has_note ->
[true] : {$note}
*[other] {\"\"}
}"),
DeprecatedSinceKind::InFuture => inline_fluent!("use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note ->
[true] : {$note}
*[other] {\"\"}
}"),
DeprecatedSinceKind::InVersion(_) => {
inline_fluent!("use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note ->
DeprecatedSinceKind::InEffect => inline_fluent!(
"use of deprecated {$kind} `{$path}`{$has_note ->
[true] : {$note}
*[other] {\"\"}
}")
}"
),
DeprecatedSinceKind::InFuture => inline_fluent!(
"use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note ->
[true] : {$note}
*[other] {\"\"}
}"
),
DeprecatedSinceKind::InVersion(_) => {
inline_fluent!(
"use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note ->
[true] : {$note}
*[other] {\"\"}
}"
)
}
});
diag.arg("kind", self.kind);

View file

@ -542,10 +542,12 @@ impl Subdiagnostic for LocalLabel<'_> {
dtor.add_to_diag(diag);
}
let msg =
diag.eagerly_translate(inline_fluent!("{$is_dropped_first_edition_2024 ->
[true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024
*[false] `{$name}` will be dropped later as of Edition 2024
}"));
diag.eagerly_translate(inline_fluent!(
"{$is_dropped_first_edition_2024 ->
[true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024
*[false] `{$name}` will be dropped later as of Edition 2024
}"
));
diag.span_label(self.span, msg);
}
}

View file

@ -2,12 +2,12 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(assert_matches))]
#![cfg_attr(test, feature(iter_order_by))]
#![feature(box_patterns)]
#![feature(debug_closure_helpers)]
#![feature(default_field_values)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![recursion_limit = "256"]
// tidy-alphabetical-end

View file

@ -308,6 +308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcDelayedBugFromInsideQuery
| AttributeKind::RustcDenyExplicitImpl(..)
| AttributeKind::RustcDeprecatedSafe2024 {..}
| AttributeKind::RustcDiagnosticItem(..)
| AttributeKind::RustcDummy
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpItemBounds
@ -392,13 +393,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::warn
| sym::deny
| sym::forbid
// need to be fixed
| sym::deprecated_safe // FIXME(deprecated_safe)
// internal
| sym::panic_handler
| sym::lang
| sym::default_lib_allocator
| sym::rustc_diagnostic_item
| sym::rustc_nonnull_optimization_guaranteed
| sym::rustc_inherit_overflow_checks
| sym::rustc_on_unimplemented

View file

@ -9,20 +9,21 @@
//!
//! * Compiler internal types like `Ty` and `TyCtxt`
use rustc_hir::attrs::AttributeKind;
use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_hir::{Attribute, CRATE_OWNER_ID, OwnerId};
use rustc_hir::{CRATE_OWNER_ID, OwnerId, find_attr};
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::{Symbol, sym};
use crate::errors::DuplicateDiagnosticItemInCrate;
fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
let attrs = tcx.hir_attrs(owner.into());
if let Some(name) = extract(attrs) {
if let Some(name) = find_attr!(attrs, AttributeKind::RustcDiagnosticItem(name) => name) {
// insert into our table
collect_item(tcx, diagnostic_items, name, owner.to_def_id());
collect_item(tcx, diagnostic_items, *name, owner.to_def_id());
}
}
@ -53,13 +54,6 @@ fn report_duplicate_item(
});
}
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(attrs: &[Attribute]) -> Option<Symbol> {
attrs.iter().find_map(|attr| {
if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
})
}
/// Traverse and collect the diagnostic items in the current
fn diagnostic_items(tcx: TyCtxt<'_>, _: LocalCrate) -> DiagnosticItems {
// Initialize the collector.

View file

@ -684,9 +684,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr {
// There were some functions named `main` though. Try to give the user a hint.
inline_fluent!(
"the main function must be defined at the crate level{$has_filename ->
[true] {\" \"}(in `{$filename}`)
*[false] {\"\"}
}"
[true] {\" \"}(in `{$filename}`)
*[false] {\"\"}
}"
)
} else if self.has_filename {
inline_fluent!("consider adding a `main` function to `{$filename}`")

View file

@ -4,11 +4,6 @@
//!
//! This API is completely unstable and subject to change.
// tidy-alphabetical-start
#![feature(if_let_guard)]
#![feature(map_try_insert)]
// tidy-alphabetical-end
use rustc_middle::query::Providers;
pub mod abi_test;

View file

@ -4,7 +4,6 @@
// tidy-alphabetical-start
#![allow(unused_crate_dependencies)]
#![cfg_attr(feature = "rustc", feature(if_let_guard))]
// tidy-alphabetical-end
pub(crate) mod checks;

View file

@ -14,7 +14,6 @@
// tidy-alphabetical-start
#![allow(rustc::usage_of_ty_tykind)]
#![doc(test(attr(allow(unused_variables), deny(warnings), allow(internal_features))))]
#![feature(sized_hierarchy)]
#![feature(trait_alias)]
// tidy-alphabetical-end

View file

@ -0,0 +1,174 @@
use rustc_middle::bug;
use rustc_middle::dep_graph::DepKindVTable;
use rustc_middle::ty::TyCtxt;
use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle};
use rustc_query_system::query::QueryCache;
use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner};
use crate::{QueryCtxt, QueryDispatcherUnerased, QueryFlags};
/// [`DepKindVTable`] constructors for special dep kinds that aren't queries.
#[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")]
mod non_query {
use super::*;
// We use this for most things when incr. comp. is turned off.
pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|_, dep_node, _| {
bug!("force_from_dep_node: encountered {dep_node:?}")
}),
try_load_from_on_disk_cache: None,
name: &"Null",
}
}
// We use this for the forever-red node.
pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|_, dep_node, _| {
bug!("force_from_dep_node: encountered {dep_node:?}")
}),
try_load_from_on_disk_cache: None,
name: &"Red",
}
}
pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|tcx, _, prev_index| {
tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
true
}),
try_load_from_on_disk_cache: None,
name: &"SideEffect",
}
}
pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
try_load_from_on_disk_cache: None,
name: &"AnonZeroDeps",
}
}
pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"TraitSelect",
}
}
pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"CompileCodegenUnit",
}
}
pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"CompileMonoItem",
}
}
pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"Metadata",
}
}
}
/// Shared implementation of the [`DepKindVTable`] constructor for queries.
/// Called from macro-generated code for each query.
pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q, Cache, const FLAGS: QueryFlags>(
is_eval_always: bool,
) -> DepKindVTable<'tcx>
where
Q: QueryDispatcherUnerased<'tcx, Cache, FLAGS>,
Cache: QueryCache + 'tcx,
{
let is_anon = FLAGS.is_anon;
let fingerprint_style = if is_anon {
FingerprintStyle::Opaque
} else {
<Cache::Key as DepNodeKey<TyCtxt<'tcx>>>::fingerprint_style()
};
if is_anon || !fingerprint_style.reconstructible() {
return DepKindVTable {
is_anon,
is_eval_always,
fingerprint_style,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: Q::NAME,
};
}
DepKindVTable {
is_anon,
is_eval_always,
fingerprint_style,
force_from_dep_node: Some(|tcx, dep_node, _| {
force_from_dep_node_inner(Q::query_dispatcher(tcx), tcx, dep_node)
}),
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
try_load_from_on_disk_cache_inner(Q::query_dispatcher(tcx), tcx, dep_node)
}),
name: Q::NAME,
}
}
/// Helper module containing a [`DepKindVTable`] constructor for each dep kind,
/// for use with [`rustc_middle::make_dep_kind_array`].
///
/// That macro will check that we gave it a constructor for every known dep kind.
mod _dep_kind_vtable_ctors {
// Re-export all of the vtable constructors for non-query and query dep kinds.
// Non-query vtable constructors are defined in normal code.
pub(crate) use super::non_query::*;
// Query vtable constructors are defined via a macro.
pub(crate) use crate::_dep_kind_vtable_ctors_for_queries::*;
}
pub fn make_dep_kind_vtables<'tcx>(
arena: &'tcx rustc_middle::arena::Arena<'tcx>,
) -> &'tcx [DepKindVTable<'tcx>] {
// Create an array of vtables, one for each dep kind (non-query and query).
let dep_kind_vtables: [DepKindVTable<'tcx>; _] =
rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors);
arena.alloc_from_iter(dep_kind_vtables)
}

View file

@ -12,8 +12,7 @@
use std::marker::ConstParamTy;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNode, DepNodeIndex};
use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex};
use rustc_middle::queries::{
self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
};
@ -27,6 +26,7 @@ use rustc_query_system::query::{
};
use rustc_span::{ErrorGuaranteed, Span};
pub use crate::dep_kind_vtables::make_dep_kind_vtables;
pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack};
pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all};
use crate::plumbing::{encode_all_query_results, try_mark_green};
@ -34,11 +34,13 @@ use crate::profiling_support::QueryKeyStringCache;
pub use crate::profiling_support::alloc_self_profile_query_strings;
use crate::values::Value;
#[macro_use]
mod plumbing;
mod dep_kind_vtables;
mod error;
mod execution;
mod job;
#[macro_use]
mod plumbing;
mod profiling_support;
mod values;

View file

@ -13,9 +13,10 @@ use rustc_hir::def_id::DefId;
use rustc_hir::limit::Limit;
use rustc_index::Idx;
use rustc_middle::bug;
#[expect(unused_imports, reason = "used by doc comments")]
use rustc_middle::dep_graph::DepKindVTable;
use rustc_middle::dep_graph::{
self, DepContext, DepKindVTable, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex,
dep_kinds,
self, DepContext, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex, dep_kinds,
};
use rustc_middle::query::Key;
use rustc_middle::query::on_disk_cache::{
@ -26,7 +27,7 @@ use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::print::with_reduced_queries;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext};
use rustc_query_system::dep_graph::{DepNodeKey, HasDepContext};
use rustc_query_system::query::{
QueryCache, QueryContext, QueryJobId, QuerySideEffect, QueryStackDeferred, QueryStackFrame,
QueryStackFrameExtra,
@ -447,7 +448,8 @@ pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache, const FLAGS: QueryFlags
});
}
fn try_load_from_on_disk_cache<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
/// Implementation of [`DepKindVTable::try_load_from_on_disk_cache`] for queries.
pub(crate) fn try_load_from_on_disk_cache_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
tcx: TyCtxt<'tcx>,
dep_node: DepNode,
@ -496,7 +498,8 @@ where
value
}
fn force_from_dep_node<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
/// Implementation of [`DepKindVTable::force_from_dep_node`] for queries.
pub(crate) fn force_from_dep_node_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
tcx: TyCtxt<'tcx>,
dep_node: DepNode,
@ -527,49 +530,6 @@ fn force_from_dep_node<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
}
}
pub(crate) fn make_dep_kind_vtable_for_query<
'tcx,
Q,
C: QueryCache + 'tcx,
const FLAGS: QueryFlags,
>(
is_eval_always: bool,
) -> DepKindVTable<'tcx>
where
Q: QueryDispatcherUnerased<'tcx, C, FLAGS>,
{
let is_anon = FLAGS.is_anon;
let fingerprint_style = if is_anon {
FingerprintStyle::Opaque
} else {
<C::Key as DepNodeKey<TyCtxt<'tcx>>>::fingerprint_style()
};
if is_anon || !fingerprint_style.reconstructible() {
return DepKindVTable {
is_anon,
is_eval_always,
fingerprint_style,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: Q::NAME,
};
}
DepKindVTable {
is_anon,
is_eval_always,
fingerprint_style,
force_from_dep_node: Some(|tcx, dep_node, _| {
force_from_dep_node(Q::query_dispatcher(tcx), tcx, dep_node)
}),
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
try_load_from_on_disk_cache(Q::query_dispatcher(tcx), tcx, dep_node)
}),
name: Q::NAME,
}
}
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_with_all_queries`.
macro_rules! define_queries {
@ -882,119 +842,20 @@ macro_rules! define_queries {
for<'tcx> fn(TyCtxt<'tcx>)
] = &[$(query_impl::$name::query_key_hash_verify),*];
/// Module containing a named function for each dep kind (including queries)
/// that creates a `DepKindVTable`.
///
/// Consumed via `make_dep_kind_array!` to create a list of vtables.
#[expect(non_snake_case)]
mod _dep_kind_vtable_ctors {
use super::*;
use rustc_middle::bug;
use rustc_query_system::dep_graph::FingerprintStyle;
/// Declares a dep-kind vtable constructor for each query.
mod _dep_kind_vtable_ctors_for_queries {
use ::rustc_middle::dep_graph::DepKindVTable;
use $crate::dep_kind_vtables::make_dep_kind_vtable_for_query;
// We use this for most things when incr. comp. is turned off.
pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
try_load_from_on_disk_cache: None,
name: &"Null",
$(
/// `DepKindVTable` constructor for this query.
pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> {
use $crate::query_impl::$name::QueryType;
make_dep_kind_vtable_for_query::<QueryType<'tcx>, _, _>(
is_eval_always!([$($modifiers)*]),
)
}
}
// We use this for the forever-red node.
pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
try_load_from_on_disk_cache: None,
name: &"Red",
}
}
pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: Some(|tcx, _, prev_index| {
tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
true
}),
try_load_from_on_disk_cache: None,
name: &"SideEffect",
}
}
pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
try_load_from_on_disk_cache: None,
name: &"AnonZeroDeps",
}
}
pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"TraitSelect",
}
}
pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"CompileCodegenUnit",
}
}
pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Opaque,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"CompileMonoItem",
}
}
pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"Metadata",
}
}
$(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> {
use $crate::query_impl::$name::QueryType;
$crate::plumbing::make_dep_kind_vtable_for_query::<QueryType<'tcx>, _, _>(
is_eval_always!([$($modifiers)*]),
)
})*
}
pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors))
)*
}
}
}

View file

@ -1425,14 +1425,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// a note about editions
let note = if let Some(did) = did {
let requires_note = !did.is_local()
&& this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
|attr| {
[sym::TryInto, sym::TryFrom, sym::FromIterator]
.map(|x| Some(x))
.contains(&attr.value_str())
},
&& find_attr!(
this.tcx.get_all_attrs(did),
AttributeKind::RustcDiagnosticItem(
sym::TryInto | sym::TryFrom | sym::FromIterator
)
);
requires_note.then(|| {
format!(
"'{}' is included in the prelude starting in Edition 2021",

View file

@ -21,7 +21,7 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{MissingLifetimeKind, PrimTy};
use rustc_hir::{MissingLifetimeKind, PrimTy, find_attr};
use rustc_middle::ty;
use rustc_session::{Session, lint};
use rustc_span::edit_distance::{edit_distance, find_best_match_for_name};
@ -2446,10 +2446,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
.iter()
.filter_map(|candidate| candidate.did)
.find(|did| {
self.r
.tcx
.get_attrs(*did, sym::rustc_diagnostic_item)
.any(|attr| attr.value_str() == Some(sym::Default))
find_attr!(
self.r.tcx.get_all_attrs(*did),
AttributeKind::RustcDiagnosticItem(sym::Default)
)
});
let Some(default_trait) = default_trait else {
return;

View file

@ -15,7 +15,6 @@
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(control_flow_into_value)]
#![feature(decl_macro)]
#![feature(default_field_values)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]

View file

@ -3,7 +3,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::internal)]
#![cfg_attr(test, feature(test))]
#![doc(test(attr(allow(unused_variables), deny(warnings), allow(internal_features))))]
#![feature(core_intrinsics)]
#![feature(min_specialization)]

View file

@ -32,7 +32,7 @@ There are three main thread states:
waiting to be awoken.
We sometimes refer to the final two states collectively as **inactive**.
Threads begin as idle but transition to idle and finally sleeping when
Threads begin as active but transition to idle and finally sleeping when
they're unable to find work to do.
## Sleepy threads
@ -160,7 +160,7 @@ not complete. It is possible -- if unlikely -- that enough activity occurs for
Thread A to observe the same JEC value that it saw when getting sleepy. If the
new work being published came from *inside* the thread-pool, then this race
condition isn't too harmful. It means that we have fewer workers processing the
work then we should, but we won't deadlock. This seems like an acceptable risk
work than we should, but we won't deadlock. This seems like an acceptable risk
given that this is unlikely in practice.
However, if the work was posted as an *external* job, that is a problem. In that

View file

@ -252,10 +252,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
SubregionOrigin::RelateParamBound(span, ty, opt_span) => {
RegionOriginNote::WithName {
span,
msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
[true] ...
*[false] {\"\"}
}"),
msg: inline_fluent!(
"...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
[true] ...
*[false] {\"\"}
}"
),
name: &self.ty_to_string(ty),
continues: opt_span.is_some(),
}

View file

@ -102,10 +102,16 @@ pub struct NegativePositiveConflict<'tcx> {
impl<G: EmissionGuarantee> Diagnostic<'_, G> for NegativePositiveConflict<'_> {
#[track_caller]
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
let mut diag = Diag::new(dcx, level, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
[none] {\"\"}
*[default] {\" \"}for type `{$self_desc}`
}:"));
let mut diag = Diag::new(
dcx,
level,
inline_fluent!(
"found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
[none] {\"\"}
*[default] {\" \"}for type `{$self_desc}`
}:"
),
);
diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
diag.span(self.impl_span);
@ -157,9 +163,9 @@ impl Subdiagnostic for AdjustSignatureBorrow {
diag.multipart_suggestion_verbose(
inline_fluent!(
"consider adjusting the signature so it borrows its {$borrow_len ->
[one] argument
*[other] arguments
}"
[one] argument
*[other] arguments
}"
),
to_borrow,
Applicability::MaybeIncorrect,
@ -170,9 +176,9 @@ impl Subdiagnostic for AdjustSignatureBorrow {
diag.multipart_suggestion_verbose(
inline_fluent!(
"consider adjusting the signature so it does not borrow its {$remove_borrow_len ->
[one] argument
*[other] arguments
}"
[one] argument
*[other] arguments
}"
),
remove_borrow,
Applicability::MaybeIncorrect,
@ -505,18 +511,18 @@ impl Subdiagnostic for RegionOriginNote<'_> {
span,
inline_fluent!(
"...so that the {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
),
);
diag.arg("requirement", requirement);
@ -531,18 +537,18 @@ impl Subdiagnostic for RegionOriginNote<'_> {
span,
inline_fluent!(
"...so that {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
),
);
diag.arg("requirement", requirement);
@ -578,9 +584,9 @@ impl Subdiagnostic for LifetimeMismatchLabels {
span,
inline_fluent!(
"...but data{$label_var1_exists ->
[true] {\" \"}from `{$label_var1}`
*[false] {\"\"}
} is returned here"
[true] {\" \"}from `{$label_var1}`
*[false] {\"\"}
} is returned here"
),
);
diag.arg("label_var1_exists", label_var1.is_some());
@ -614,12 +620,12 @@ impl Subdiagnostic for LifetimeMismatchLabels {
span,
inline_fluent!(
"...but data{$label_var1_exists ->
[true] {\" \"}from `{$label_var1}`
*[false] {\"\"}
} flows{$label_var2_exists ->
[true] {\" \"}into `{$label_var2}`
*[false] {\"\"}
} here"
[true] {\" \"}from `{$label_var1}`
*[false] {\"\"}
} flows{$label_var2_exists ->
[true] {\" \"}into `{$label_var2}`
*[false] {\"\"}
} here"
),
);
diag.arg("label_var1_exists", label_var1.is_some());
@ -789,12 +795,12 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
diag.multipart_suggestion_verbose(
inline_fluent!(
"consider {$is_reuse ->
[true] reusing
*[false] introducing
} a named lifetime parameter{$is_impl ->
[true] {\" \"}and update trait if needed
*[false] {\"\"}
}"
[true] reusing
*[false] introducing
} a named lifetime parameter{$is_impl ->
[true] {\" \"}and update trait if needed
*[false] {\"\"}
}"
),
visitor.suggestions,
Applicability::MaybeIncorrect,

View file

@ -171,37 +171,37 @@ impl Subdiagnostic for RegionExplanation<'_> {
let msg = diag.eagerly_translate(inline_fluent!(
"{$pref_kind ->
*[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {\"\"}
}{$pref_kind ->
[empty] {\"\"}
*[other] {\" \"}
}{$desc_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
[revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
[defined_here_reg] the lifetime `{$desc_arg}` as defined here
}{$suff_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{\"\"}
[continues] ...
[req_by_binding] {\" \"}as required by this binding
}"
*[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {\"\"}
}{$pref_kind ->
[empty] {\"\"}
*[other] {\" \"}
}{$desc_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
[revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
[defined_here_reg] the lifetime `{$desc_arg}` as defined here
}{$suff_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{\"\"}
[continues] ...
[req_by_binding] {\" \"}as required by this binding
}"
));
diag.restore_args();
if let Some(span) = self.desc.span {

View file

@ -430,7 +430,16 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
}
};
prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap()
prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap_or_else(|| {
// This can happen if the trait hierarchy is malformed (e.g., due to
// missing generics on a supertrait bound). There should already be an error
// emitted for this, so we just delay the ICE.
tcx.dcx().delayed_bug(format!(
"could not find the supertrait vtable slot for `{}` -> `{}`",
source, target
));
None
})
}
pub(super) fn provide(providers: &mut Providers) {

View file

@ -5,10 +5,7 @@
#![allow(rustc::usage_of_type_ir_inherent)]
#![allow(rustc::usage_of_type_ir_traits)]
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(
feature = "nightly",
feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
)]
#![cfg_attr(feature = "nightly", feature(associated_type_defaults, rustc_attrs, negative_impls))]
// tidy-alphabetical-end
extern crate self as rustc_type_ir;

View file

@ -1514,7 +1514,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// Recreate a `Box` which was previously converted to a `NonNull` pointer
/// using [`Box::into_non_null_with_allocator`]:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///
@ -1524,7 +1524,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// ```
/// Manually create a `Box` from scratch by using the system allocator:
/// ```
/// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)]
/// #![feature(allocator_api)]
///
/// use std::alloc::{Allocator, Layout, System};
///
@ -1629,7 +1629,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// Converting the `NonNull` pointer back into a `Box` with
/// [`Box::from_non_null_in`] for automatic cleanup:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///
@ -1640,7 +1640,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// Manual cleanup by explicitly running the destructor and deallocating
/// the memory:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::{Allocator, Layout, System};
///

View file

@ -56,6 +56,7 @@
//! [`Rc`]: rc
//! [`RefCell`]: core::cell
#![allow(unused_features)]
#![allow(incomplete_features)]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
@ -85,13 +86,11 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))]
#![feature(allocator_api)]
#![feature(array_into_iter_constructors)]
#![feature(ascii_char)]
#![feature(async_fn_traits)]
#![feature(async_iterator)]
#![feature(box_vec_non_null)]
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(cast_maybe_uninit)]
@ -148,7 +147,6 @@
#![feature(slice_ptr_get)]
#![feature(slice_range)]
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(temporary_niche_types)]
#![feature(transmutability)]
#![feature(trivial_clone)]
@ -158,7 +156,6 @@
#![feature(try_blocks)]
#![feature(try_trait_v2)]
#![feature(try_trait_v2_residual)]
#![feature(try_with_capacity)]
#![feature(tuple_trait)]
#![feature(ub_checks)]
#![feature(unicode_internals)]
@ -176,10 +173,8 @@
#![feature(const_trait_impl)]
#![feature(coroutine_trait)]
#![feature(decl_macro)]
#![feature(derive_const)]
#![feature(dropck_eyepatch)]
#![feature(fundamental)]
#![feature(hashmap_internals)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(min_specialization)]

View file

@ -1238,7 +1238,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///
@ -1265,7 +1265,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// Using memory that was allocated elsewhere:
///
/// ```rust
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::{AllocError, Allocator, Global, Layout};
///
@ -1365,7 +1365,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///

View file

@ -16,7 +16,6 @@
// tidy-alphabetical-start
#![feature(allocator_api)]
#![feature(array_into_iter_constructors)]
#![feature(box_vec_non_null)]
#![feature(char_internals)]
#![feature(const_alloc_error)]
#![feature(const_cmp)]
@ -55,16 +54,12 @@
//
// Language features:
// tidy-alphabetical-start
#![feature(cfg_sanitize)]
#![feature(const_trait_impl)]
#![feature(dropck_eyepatch)]
#![feature(lang_items)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(optimize_attribute)]
#![feature(prelude_import)]
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![feature(test)]

View file

@ -3,7 +3,6 @@
#![feature(const_heap)]
#![feature(deque_extend_front)]
#![feature(iter_array_chunks)]
#![feature(wtf8_internals)]
#![feature(cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(downcast_unchecked)]
@ -30,8 +29,6 @@
#![feature(string_remove_matches)]
#![feature(const_btree_len)]
#![feature(const_trait_impl)]
#![feature(panic_update_hook)]
#![feature(pointer_is_aligned_to)]
#![feature(test)]
#![feature(thin_box)]
#![feature(drain_keep_rest)]

View file

@ -878,7 +878,7 @@ impl AsciiChar {
/// # Examples
///
/// ```
/// #![feature(ascii_char, ascii_char_variants, is_ascii_octdigit)]
/// #![feature(ascii_char, ascii_char_variants)]
///
/// use std::ascii;
///

View file

@ -774,7 +774,6 @@ impl<T, const N: usize> Cell<[T; N]> {
/// following is unsound:
///
/// ```rust
/// #![feature(cell_get_cloned)]
/// # use std::cell::Cell;
///
/// #[derive(Copy, Debug)]

View file

@ -219,6 +219,7 @@ impl_float_from_bool!(
f16;
doctest_prefix:
// rustdoc doesn't remove the conventional space after the `///`
///# #![allow(unused_features)]
///#![feature(f16)]
///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///
@ -230,6 +231,7 @@ impl_float_from_bool!(f64);
impl_float_from_bool!(
f128;
doctest_prefix:
///# #![allow(unused_features)]
///#![feature(f128)]
///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///

View file

@ -87,6 +87,7 @@
#![allow(incomplete_features)]
#![warn(multiple_supertrait_upcastable)]
#![allow(internal_features)]
#![allow(unused_features)]
#![deny(ffi_unwind_calls)]
#![warn(unreachable_pub)]
// Do not check link redundancy on bootstrapping phase
@ -95,9 +96,7 @@
//
// Library features:
// tidy-alphabetical-start
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(cfg_select)]
#![feature(cfg_target_has_reliable_f16_f128)]
@ -106,31 +105,15 @@
#![feature(const_destruct)]
#![feature(const_eval_select)]
#![feature(const_select_unpredictable)]
#![feature(const_unsigned_bigint_helpers)]
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
#![feature(disjoint_bitor)]
#![feature(internal_impls_macro)]
#![feature(ip)]
#![feature(is_ascii_octdigit)]
#![feature(link_cfg)]
#![feature(offset_of_enum)]
#![feature(panic_internals)]
#![feature(pattern_type_macro)]
#![feature(ptr_alignment_type)]
#![feature(ptr_metadata)]
#![feature(set_ptr_value)]
#![feature(signed_bigint_helpers)]
#![feature(slice_ptr_get)]
#![feature(str_internals)]
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
#![feature(type_info)]
#![feature(ub_checks)]
#![feature(unsafe_pinned)]
#![feature(utf16_extra)]
#![feature(variant_count)]
#![feature(widening_mul)]
// tidy-alphabetical-end
//
// Language features:
@ -175,7 +158,6 @@
#![feature(optimize_attribute)]
#![feature(pattern_types)]
#![feature(prelude_import)]
#![feature(reborrow)]
#![feature(repr_simd)]
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]

View file

@ -148,7 +148,10 @@ pub mod consts {
pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128;
}
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
#[doc(test(attr(
feature(cfg_target_has_reliable_f16_f128),
allow(internal_features, unused_features)
)))]
impl f128 {
/// The radix or base of the internal representation of `f128`.
#[unstable(feature = "f128", issue = "116909")]
@ -1470,7 +1473,11 @@ impl f128 {
// Functions in this module fall into `core_float_math`
// #[unstable(feature = "core_float_math", issue = "137578")]
#[cfg(not(test))]
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))]
#[doc(test(attr(
feature(cfg_target_has_reliable_f16_f128),
expect(internal_features),
allow(unused_features)
)))]
impl f128 {
/// Returns the largest integer less than or equal to `self`.
///

View file

@ -142,7 +142,10 @@ pub mod consts {
pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16;
}
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
#[doc(test(attr(
feature(cfg_target_has_reliable_f16_f128),
allow(internal_features, unused_features)
)))]
impl f16 {
/// The radix or base of the internal representation of `f16`.
#[unstable(feature = "f16", issue = "116909")]

View file

@ -1821,6 +1821,7 @@ pub mod math {
/// # Examples
///
/// ```
/// # #![allow(unused_features)]
/// #![feature(core_float_math)]
///
/// # // FIXME(#140515): mingw has an incorrect fma

View file

@ -1819,6 +1819,7 @@ pub mod math {
/// # Examples
///
/// ```
/// # #![allow(unused_features)]
/// #![feature(core_float_math)]
///
/// # // FIXME(#140515): mingw has an incorrect fma

View file

@ -3072,7 +3072,6 @@ macro_rules! uint_impl {
/// implementing it for wider-than-native types.
///
/// ```
/// #![feature(const_unsigned_bigint_helpers)]
/// fn scalar_mul_eq(little_endian_digits: &mut Vec<u16>, multiplicand: u16) {
/// let mut carry = 0;
/// for d in little_endian_digits.iter_mut() {
@ -3097,6 +3096,7 @@ macro_rules! uint_impl {
/// except that it gives the value of the overflow instead of just whether one happened:
///
/// ```
/// # #![allow(unused_features)]
/// #![feature(const_unsigned_bigint_helpers)]
/// let r = u8::carrying_mul(7, 13, 0);
/// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
@ -3109,6 +3109,7 @@ macro_rules! uint_impl {
/// [`wrapping_add`](Self::wrapping_add) methods:
///
/// ```
/// # #![allow(unused_features)]
/// #![feature(const_unsigned_bigint_helpers)]
/// assert_eq!(
/// 789_u16.carrying_mul(456, 123).0,

View file

@ -112,7 +112,6 @@ impl Alignment {
///
/// ```
/// #![feature(ptr_alignment_type)]
/// #![feature(layout_for_ptr)]
/// use std::ptr::Alignment;
///
/// assert_eq!(unsafe { Alignment::of_val_raw(&5i32) }.as_usize(), 4);

View file

@ -1800,7 +1800,6 @@ impl<T> *mut [T] {
///
/// ```
/// #![feature(raw_slice_split)]
/// #![feature(slice_ptr_get)]
///
/// let mut v = [1, 0, 3, 0, 5, 6];
/// let ptr = &mut v as *mut [_];

View file

@ -690,7 +690,6 @@ impl Duration {
/// # Examples
///
/// ```
/// #![feature(duration_constants)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
@ -801,7 +800,6 @@ impl Duration {
/// # Examples
///
/// ```
/// #![feature(duration_constants)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));

View file

@ -13,7 +13,6 @@
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(char_internals)]
#![feature(char_max_len)]
#![feature(clamp_magnitude)]
#![feature(clone_to_uninit)]
#![feature(const_array)]
#![feature(const_bool)]
@ -35,7 +34,6 @@
#![feature(const_trait_impl)]
#![feature(const_unsigned_bigint_helpers)]
#![feature(control_flow_ok)]
#![feature(core_float_math)]
#![feature(core_intrinsics)]
#![feature(core_intrinsics_fallbacks)]
#![feature(core_io_borrowed_buf)]
@ -47,7 +45,6 @@
#![feature(drop_guard)]
#![feature(duration_constants)]
#![feature(duration_constructors)]
#![feature(error_generic_member_access)]
#![feature(exact_div)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
@ -55,7 +52,6 @@
#![feature(f16)]
#![feature(f128)]
#![feature(float_algebraic)]
#![feature(float_gamma)]
#![feature(float_minimum_maximum)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
@ -94,7 +90,6 @@
#![feature(nonzero_from_str_radix)]
#![feature(numfmt)]
#![feature(one_sided_range)]
#![feature(option_reduce)]
#![feature(pattern)]
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
@ -114,7 +109,6 @@
#![feature(step_trait)]
#![feature(str_internals)]
#![feature(strict_provenance_lints)]
#![feature(test)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_blocks)]

View file

@ -17,7 +17,6 @@
#![feature(cfg_emscripten_wasm_eh)]
#![feature(cfg_select)]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(panic_unwind)]
#![feature(staged_api)]
#![feature(std_internals)]
@ -25,6 +24,7 @@
#![panic_runtime]
#![feature(panic_runtime)]
#![allow(internal_features)]
#![allow(unused_features)]
#![warn(unreachable_pub)]
#![deny(unsafe_op_in_unsafe_fn)]

View file

@ -16,6 +16,7 @@ use crate::intrinsics;
use crate::sys::cmath;
#[cfg(not(test))]
#[doc(test(attr(allow(unused_features))))]
impl f128 {
/// Raises a number to a floating point power.
///

View file

@ -916,7 +916,6 @@ impl f16 {
///
/// ```
/// #![feature(f16)]
/// #![feature(float_gamma)]
/// # #[cfg(not(miri))]
/// # #[cfg(target_has_reliable_f16_math)] {
///
@ -952,7 +951,6 @@ impl f16 {
///
/// ```
/// #![feature(f16)]
/// #![feature(float_gamma)]
/// # #[cfg(not(miri))]
/// # #[cfg(target_has_reliable_f16_math)] {
///
@ -988,7 +986,6 @@ impl f16 {
///
/// ```
/// #![feature(f16)]
/// #![feature(float_erf)]
/// # #[cfg(not(miri))]
/// # #[cfg(target_has_reliable_f16_math)] {
/// /// The error function relates what percent of a normal distribution lies
@ -1028,7 +1025,6 @@ impl f16 {
///
/// ```
/// #![feature(f16)]
/// #![feature(float_erf)]
/// # #[cfg(not(miri))]
/// # #[cfg(target_has_reliable_f16_math)] {
/// let x: f16 = 0.123;

View file

@ -1,4 +1,4 @@
#![feature(f16, f128, float_gamma, float_minimum_maximum, cfg_target_has_reliable_f16_f128)]
#![feature(f16, f128, float_gamma, cfg_target_has_reliable_f16_f128)]
#![expect(internal_features)] // for reliable_f16_f128
use std::fmt;

View file

@ -1,5 +1,4 @@
#![allow(stable_features)]
#![feature(volatile)]
use std::ptr::{read_volatile, write_volatile};

View file

@ -1,4 +1,4 @@
#![allow(internal_features)]
#![allow(internal_features, unused_features)]
#![feature(stdarch_internal)]
#![cfg_attr(target_arch = "arm", feature(stdarch_arm_feature_detection))]
#![cfg_attr(

View file

@ -1,4 +1,4 @@
#![allow(internal_features)]
#![allow(internal_features, unused_features)]
#![cfg_attr(
any(
target_arch = "arm",

View file

@ -24,7 +24,7 @@
#![feature(staged_api)]
#![feature(process_exitcode_internals)]
#![feature(panic_can_unwind)]
#![feature(test)]
#![cfg_attr(test, feature(test))]
#![feature(thread_spawn_hook)]
#![allow(internal_features)]
#![warn(rustdoc::unescaped_backticks)]

View file

@ -4,12 +4,12 @@
#![feature(cfg_select)]
#![feature(link_cfg)]
#![feature(staged_api)]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
#![cfg_attr(
all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
feature(link_llvm_intrinsics, simd_wasm64)
)]
#![allow(internal_features)]
#![allow(unused_features)]
#![deny(unsafe_op_in_unsafe_fn)]
// Force libc to be included even if unused. This is required by many platforms.

View file

@ -175,8 +175,8 @@ When you use bootstrap, you'll call it through the entry point script
(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`.
`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
before the Rust compiler is built! To work around this, there are two components
of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py`
is what gets run by entry point script. It takes care of downloading the prebuilt
of bootstrap: the main one written in Rust, and `bootstrap.py`. `bootstrap.py`
is what gets run by the entry point script. It takes care of downloading the prebuilt
stage 0 compiler, std and Cargo binaries, which are then used to build the
bootstrap binary.

View file

@ -479,7 +479,7 @@ def default_build_triple(verbose):
@contextlib.contextmanager
def output(filepath):
tmp = filepath + ".tmp"
with open(tmp, "w") as f:
with open(tmp, "w", encoding="utf-8") as f:
yield f
try:
if os.path.exists(filepath):
@ -778,7 +778,7 @@ class RustBuild(object):
# Use `/etc/os-release` instead of `/etc/NIXOS`.
# The latter one does not exist on NixOS when using tmpfs as root.
try:
with open("/etc/os-release", "r") as f:
with open("/etc/os-release", "r", encoding="utf-8") as f:
is_nixos = any(
ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"')
for ln in f
@ -863,7 +863,8 @@ class RustBuild(object):
if ".so" not in fname:
# Finally, set the correct .interp for binaries
with open(
"{}/nix-support/dynamic-linker".format(nix_deps_dir)
"{}/nix-support/dynamic-linker".format(nix_deps_dir),
encoding="utf-8",
) as dynamic_linker:
patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()]
@ -888,7 +889,7 @@ class RustBuild(object):
"""Check if the given program stamp is out of date"""
if not os.path.exists(stamp_path) or self.clean:
return True
with open(stamp_path, "r") as stamp:
with open(stamp_path, "r", encoding="utf-8") as stamp:
return key != stamp.read()
def bin_root(self):
@ -1276,7 +1277,7 @@ def parse_args(args):
def parse_stage0_file(path):
result = {}
with open(path, "r") as file:
with open(path, "r", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line and not line.startswith("#"):
@ -1346,7 +1347,7 @@ def bootstrap(args):
# HACK: This works because `self.get_toml()` returns the first match it finds for a
# specific key, so appending our defaults at the end allows the user to override them
with open(include_path) as included_toml:
with open(include_path, encoding="utf-8") as included_toml:
config_toml += os.linesep + included_toml.read()
# Configure initial bootstrap
@ -1384,7 +1385,9 @@ def main():
if len(sys.argv) == 1 or sys.argv[1] in ["-h", "--help"]:
try:
with open(
os.path.join(os.path.dirname(__file__), "../etc/xhelp"), "r"
os.path.join(os.path.dirname(__file__), "../etc/xhelp"),
"r",
encoding="utf-8",
) as f:
# The file from bootstrap func already has newline.
print(f.read(), end="")

View file

@ -48,7 +48,7 @@ Refer to the [dev guide](https://rustc-dev-guide.rust-lang.org/tests/docker.html
## Docker Toolbox on Windows
For Windows before Windows 10, the docker images can be run on Windows via
[Docker Toolbox]. There are several preparation needs to be made before running
[Docker Toolbox]. There are several preparations that need to be made before running
a Docker image.
1. Stop the virtual machine from the terminal with `docker-machine stop`
@ -92,7 +92,7 @@ To run the image,
A number of these images take quite a long time to compile as they're building
whole gcc toolchains to do cross builds with. Much of this is relatively
self-explanatory but some images use [crosstool-ng] which isn't quite as self
explanatory. Below is a description of where these `*.defconfig` files come form,
explanatory. Below is a description of where these `*.defconfig` files come from,
how to generate them, and how the existing ones were generated.
[crosstool-ng]: https://github.com/crosstool-ng/crosstool-ng

View file

@ -189,6 +189,7 @@ target | std | notes
[`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
[`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39)
[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | ✓ |RISC-V Linux (kernel 4.20+, musl 1.2.5)
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
[`riscv64im-unknown-none-elf`](platform-support/riscv64im-unknown-none-elf.md) | * | Bare RISC-V (RV64IM ISA)
@ -406,7 +407,6 @@ target | std | host | notes
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
[`riscv64gc-unknown-redox`](platform-support/redox.md) | ✓ | | RISC-V 64bit Redox OS
[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX
[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39)
[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.5)
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+

View file

@ -6,12 +6,10 @@
)]
#![feature(ascii_char)]
#![feature(ascii_char_variants)]
#![feature(box_into_inner)]
#![feature(box_patterns)]
#![feature(file_buffered)]
#![feature(formatting_options)]
#![feature(if_let_guard)]
#![feature(iter_advance_by)]
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![feature(rustc_private)]

View file

@ -1,6 +0,0 @@
//@ known-bug: #135845
struct S<'a, T: ?Sized>(&'a T);
fn b<'a>() -> S<'static, _> {
S::<'a>(&0)
}

View file

@ -4,9 +4,10 @@
fn foo<T>() {
[0; size_of::<*mut T>()];
//~^ ERROR: tuple constructor with invalid base path
//~^ ERROR: complex const arguments must be placed inside of a `const` block
[0; const { size_of::<*mut T>() }];
//~^ ERROR: generic parameters may not be used in const operations
[0; const { size_of::<*mut i32>() }];
}
fn main() {}

View file

@ -1,4 +1,4 @@
error: tuple constructor with invalid base path
error: complex const arguments must be placed inside of a `const` block
--> $DIR/size-of-generic-ptr-in-array-len.rs:6:9
|
LL | [0; size_of::<*mut T>()];

View file

@ -32,7 +32,7 @@ fn test_errors<const N: usize>() {
//~| ERROR tuple constructor with invalid base path
accepts_point::<{ non_ctor(N, N) }>();
//~^ ERROR tuple constructor with invalid base path
//~^ ERROR complex const arguments must be placed inside of a `const` block
accepts_point::<{ CONST_ITEM(N, N) }>();
//~^ ERROR tuple constructor with invalid base path

View file

@ -27,7 +27,7 @@ error: tuple constructor with invalid base path
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^
error: tuple constructor with invalid base path
error: complex const arguments must be placed inside of a `const` block
--> $DIR/tuple_ctor_erroneous.rs:34:23
|
LL | accepts_point::<{ non_ctor(N, N) }>();

View file

@ -0,0 +1,31 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/148953>
//!
//! Unit struct constructors used as the RHS of a `type const` associated
//! const used to ICE during normalization because they were lowered as
//! `Const::new_unevaluated` with a Ctor def_id. Fixed by adding proper const
//! constructor support that produces a concrete ValTree value instead.
//@ check-pass
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;
#[derive(ConstParamTy, PartialEq, Eq)]
struct S;
impl S {
type const N: S = S;
}
#[derive(ConstParamTy, PartialEq, Eq)]
enum E {
V,
}
impl E {
type const M: E = { E::V };
}
fn main() {}

View file

@ -1,7 +0,0 @@
#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature
unsafe fn deprecated_safe_fn() {}
#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature
unsafe trait DeprecatedSafeTrait {}
fn main() {}

View file

@ -1,23 +0,0 @@
error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature
--> $DIR/feature-gate-deprecated_safe.rs:1:1
|
LL | #[deprecated_safe(since = "TBD", note = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #94978 <https://github.com/rust-lang/rust/issues/94978> for more information
= help: add `#![feature(deprecated_safe)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature
--> $DIR/feature-gate-deprecated_safe.rs:4:1
|
LL | #[deprecated_safe(since = "TBD", note = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #94978 <https://github.com/rust-lang/rust/issues/94978> for more information
= help: add `#![feature(deprecated_safe)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,11 @@
// Regression test for #135845.
use std::marker::PhantomData;
fn b<'a>() -> _ {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
let _: PhantomData<&'a ()> = PhantomData;
0
}
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/recover-infer-ret-ty-issue-135845.rs:5:15
|
LL | fn b<'a>() -> _ {
| ^ not allowed in type signatures
|
help: replace with the correct return type
|
LL - fn b<'a>() -> _ {
LL + fn b<'a>() -> i32 {
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0121`.

View file

@ -0,0 +1,21 @@
//@ check-pass
//@ compile-flags: -Znext-solver
// Regression test for trait-system-refactor-initiative#264.
//
// Some defining uses of opaque types can't constrain captured regions to universals.
// Previouly, we eagerly report error in this case.
// Now we report error only if there's no fully defining use from all bodies of the typeck root.
struct Inv<'a>(*mut &'a ());
fn mk_static() -> Inv<'static> { todo!() }
fn guide_closure_sig<'a>(f: impl FnOnce() -> Inv<'a>) {}
fn unconstrained_in_closure() -> impl Sized {
guide_closure_sig(|| unconstrained_in_closure());
mk_static()
}
fn main() {}

View file

@ -0,0 +1,34 @@
//@ compile-flags: -Znext-solver
// Just for diagnostics completeness.
// This is probably unimportant as we only report one error for such case in HIR typeck.
#![feature(type_alias_impl_trait)]
struct Invar<'a>(*mut &'a ());
fn mk_invar<'a>(a: &'a i32) -> Invar<'a> {
todo!()
}
type MultiUse = impl Sized;
#[define_opaque(MultiUse)]
fn capture_different_universals_not_on_bounds<'a, 'b, 'c>(a: &'a i32, b: &'b i32, c: &'c i32) {
let _ = || -> MultiUse {
//~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700]
mk_invar(a)
};
let _ = || -> MultiUse {
//~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700]
mk_invar(b)
};
let _ = || {
let _ = || -> MultiUse {
//~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700]
mk_invar(c)
};
};
}
fn main() {}

View file

@ -0,0 +1,36 @@
error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds
--> $DIR/report-all-unexpected-hidden-errors.rs:18:19
|
LL | type MultiUse = impl Sized;
| ---------- opaque type defined here
...
LL | let _ = || -> MultiUse {
| ^^^^^^^^
|
= note: hidden type `Invar<'_>` captures lifetime `'_`
error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds
--> $DIR/report-all-unexpected-hidden-errors.rs:22:19
|
LL | type MultiUse = impl Sized;
| ---------- opaque type defined here
...
LL | let _ = || -> MultiUse {
| ^^^^^^^^
|
= note: hidden type `Invar<'_>` captures lifetime `'_`
error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds
--> $DIR/report-all-unexpected-hidden-errors.rs:27:23
|
LL | type MultiUse = impl Sized;
| ---------- opaque type defined here
...
LL | let _ = || -> MultiUse {
| ^^^^^^^^
|
= note: hidden type `Invar<'_>` captures lifetime `'_`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0700`.

Some files were not shown because too many files have changed in this diff Show more