Auto merge of #155745 - JonathanBrouwer:rollup-D6OSAOt, r=JonathanBrouwer

Rollup of 12 pull requests

Successful merges:

 - rust-lang/rust#149452 (Refactor out common code into a `IndexItem::new` constructor)
 - rust-lang/rust#155621 (Document #[diagnostic::on_move] in the unstable book.)
 - rust-lang/rust#155635 (delegation: rename `Self` generic param to `This` in recursive delegations)
 - rust-lang/rust#155730 (Some cleanups around per parent disambiguators)
 - rust-lang/rust#153537 (rustc_codegen_ssa: Define ELF flag value for sparc-unknown-linux-gnu)
 - rust-lang/rust#155219 (Do not suggest borrowing enclosing calls for nested where-clause obligations)
 - rust-lang/rust#155408 (rustdoc: Fix Managarm C Library name in cfg pretty printer)
 - rust-lang/rust#155571 (Enable AddressSanitizer on arm-unknown-linux-gnueabihf and armv7-unknown-linux-gnueabihf)
 - rust-lang/rust#155713 (test: Add a regression test for Apple platforms aborting on `free`)
 - rust-lang/rust#155723 (Fix tier level for 5 thumb bare-metal ARM targets)
 - rust-lang/rust#155735 (Fix typo by removing extra 'to')
 - rust-lang/rust#155736 (Remove `AllVariants` workaround for rust-analyzer)
This commit is contained in:
bors
2026-04-24 17:30:32 +00:00
35 changed files with 655 additions and 155 deletions
+5 -10
View File
@@ -508,7 +508,7 @@ fn finalize_body_lowering(
// FIXME(fn_delegation): proper support for parent generics propagation // FIXME(fn_delegation): proper support for parent generics propagation
// in method call scenario. // in method call scenario.
let segment = self.process_segment(span, &segment, &mut generics.child, false); let segment = self.process_segment(span, &segment, &mut generics.child);
let segment = self.arena.alloc(segment); let segment = self.arena.alloc(segment);
self.arena.alloc(hir::Expr { self.arena.alloc(hir::Expr {
@@ -534,14 +534,10 @@ fn finalize_body_lowering(
new_path.segments = self.arena.alloc_from_iter( new_path.segments = self.arena.alloc_from_iter(
new_path.segments.iter().enumerate().map(|(idx, segment)| { new_path.segments.iter().enumerate().map(|(idx, segment)| {
let mut process_segment = |result, add_lifetimes| {
self.process_segment(span, segment, result, add_lifetimes)
};
if idx + 2 == len { if idx + 2 == len {
process_segment(&mut generics.parent, true) self.process_segment(span, segment, &mut generics.parent)
} else if idx + 1 == len { } else if idx + 1 == len {
process_segment(&mut generics.child, false) self.process_segment(span, segment, &mut generics.child)
} else { } else {
segment.clone() segment.clone()
} }
@@ -551,7 +547,7 @@ fn finalize_body_lowering(
hir::QPath::Resolved(ty, self.arena.alloc(new_path)) hir::QPath::Resolved(ty, self.arena.alloc(new_path))
} }
hir::QPath::TypeRelative(ty, segment) => { hir::QPath::TypeRelative(ty, segment) => {
let segment = self.process_segment(span, segment, &mut generics.child, false); let segment = self.process_segment(span, segment, &mut generics.child);
hir::QPath::TypeRelative(ty, self.arena.alloc(segment)) hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
} }
@@ -584,13 +580,12 @@ fn process_segment(
span: Span, span: Span,
segment: &hir::PathSegment<'hir>, segment: &hir::PathSegment<'hir>,
result: &mut GenericsGenerationResult<'hir>, result: &mut GenericsGenerationResult<'hir>,
add_lifetimes: bool,
) -> hir::PathSegment<'hir> { ) -> hir::PathSegment<'hir> {
let details = result.generics.args_propagation_details(); let details = result.generics.args_propagation_details();
let segment = if details.should_propagate { let segment = if details.should_propagate {
let generics = result.generics.into_hir_generics(self, span); let generics = result.generics.into_hir_generics(self, span);
let args = generics.into_generic_args(self, add_lifetimes, span); let args = generics.into_generic_args(self, span);
// Needed for better error messages (`trait-impl-wrong-args-count.rs` test). // Needed for better error messages (`trait-impl-wrong-args-count.rs` test).
let args = if args.is_empty() { None } else { Some(args) }; let args = if args.is_empty() { None } else { Some(args) };
@@ -6,7 +6,7 @@
use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::{bug, ty}; use rustc_middle::{bug, ty};
use rustc_span::symbol::kw; use rustc_span::symbol::kw;
use rustc_span::{Ident, Span}; use rustc_span::{Ident, Span, sym};
use crate::{LoweringContext, ResolverAstLoweringExt}; use crate::{LoweringContext, ResolverAstLoweringExt};
@@ -25,22 +25,37 @@ pub(super) enum DelegationGenericsKind {
TraitImpl(bool /* Has user-specified args */), TraitImpl(bool /* Has user-specified args */),
} }
#[derive(Debug, Clone, Copy)]
pub(super) enum GenericsPosition {
Parent,
Child,
}
pub(super) struct DelegationGenerics<T> { pub(super) struct DelegationGenerics<T> {
generics: T, generics: T,
kind: DelegationGenericsKind, kind: DelegationGenericsKind,
pos: GenericsPosition,
} }
impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> { impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> {
fn default(generics: &'hir [ty::GenericParamDef]) -> Self { fn default(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
DelegationGenerics { generics, kind: DelegationGenericsKind::Default } DelegationGenerics { generics, pos, kind: DelegationGenericsKind::Default }
} }
fn user_specified(generics: &'hir [ty::GenericParamDef]) -> Self { fn user_specified(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
DelegationGenerics { generics, kind: DelegationGenericsKind::UserSpecified } DelegationGenerics { generics, pos, kind: DelegationGenericsKind::UserSpecified }
} }
fn trait_impl(generics: &'hir [ty::GenericParamDef], user_specified: bool) -> Self { fn trait_impl(
DelegationGenerics { generics, kind: DelegationGenericsKind::TraitImpl(user_specified) } generics: &'hir [ty::GenericParamDef],
user_specified: bool,
pos: GenericsPosition,
) -> Self {
DelegationGenerics {
generics,
pos,
kind: DelegationGenericsKind::TraitImpl(user_specified),
}
} }
} }
@@ -103,8 +118,14 @@ pub(super) fn into_hir_generics(
span: Span, span: Span,
) -> &mut HirOrTyGenerics<'hir> { ) -> &mut HirOrTyGenerics<'hir> {
if let HirOrTyGenerics::Ty(ty) = self { if let HirOrTyGenerics::Ty(ty) = self {
let params = ctx.uplift_delegation_generic_params(span, ty.generics); let rename_self = matches!(ty.pos, GenericsPosition::Child);
*self = HirOrTyGenerics::Hir(DelegationGenerics { generics: params, kind: ty.kind }); let params = ctx.uplift_delegation_generic_params(span, ty.generics, rename_self);
*self = HirOrTyGenerics::Hir(DelegationGenerics {
generics: params,
kind: ty.kind,
pos: ty.pos,
});
} }
self self
@@ -120,7 +141,6 @@ fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
pub(super) fn into_generic_args( pub(super) fn into_generic_args(
&self, &self,
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>, ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
add_lifetimes: bool,
span: Span, span: Span,
) -> &'hir hir::GenericArgs<'hir> { ) -> &'hir hir::GenericArgs<'hir> {
match self { match self {
@@ -128,6 +148,7 @@ pub(super) fn into_generic_args(
bug!("Attempting to get generic args before uplifting to HIR") bug!("Attempting to get generic args before uplifting to HIR")
} }
HirOrTyGenerics::Hir(hir) => { HirOrTyGenerics::Hir(hir) => {
let add_lifetimes = matches!(hir.pos, GenericsPosition::Parent);
ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span) ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span)
} }
} }
@@ -227,10 +248,15 @@ pub(super) fn uplift_delegation_generics(
if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) { if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) {
// Considering parent generics, during signature inheritance // Considering parent generics, during signature inheritance
// we will take those args that are in trait impl header trait ref. // we will take those args that are in trait impl header trait ref.
let parent = DelegationGenerics::trait_impl(&[], true); let parent = DelegationGenerics::trait_impl(&[], true, GenericsPosition::Parent);
let parent = GenericsGenerationResult::new(parent); let parent = GenericsGenerationResult::new(parent);
let child = DelegationGenerics::trait_impl(sig_params, child_user_specified); let child = DelegationGenerics::trait_impl(
sig_params,
child_user_specified,
GenericsPosition::Child,
);
let child = GenericsGenerationResult::new(child); let child = GenericsGenerationResult::new(child);
return GenericsGenerationResults { return GenericsGenerationResults {
@@ -263,25 +289,32 @@ pub(super) fn uplift_delegation_generics(
DelegationGenerics { DelegationGenerics {
kind: DelegationGenericsKind::SelfAndUserSpecified, kind: DelegationGenericsKind::SelfAndUserSpecified,
generics: &sig_parent_params[..1], generics: &sig_parent_params[..1],
pos: GenericsPosition::Parent,
} }
} else { } else {
DelegationGenerics::user_specified(&[]) DelegationGenerics::user_specified(&[], GenericsPosition::Parent)
} }
} else { } else {
let skip_self = usize::from(!generate_self); let skip_self = usize::from(!generate_self);
DelegationGenerics::default(&sig_parent_params[skip_self..]) DelegationGenerics::default(
&sig_parent_params[skip_self..],
GenericsPosition::Parent,
)
} }
} else { } else {
DelegationGenerics::default(&[]) DelegationGenerics::default(&[], GenericsPosition::Parent)
}; };
let child_generics = if child_user_specified { let child_generics = if child_user_specified {
let synth_params_index = let synth_params_index =
sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len()); sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
DelegationGenerics::user_specified(&sig_params[synth_params_index..]) DelegationGenerics::user_specified(
&sig_params[synth_params_index..],
GenericsPosition::Child,
)
} else { } else {
DelegationGenerics::default(sig_params) DelegationGenerics::default(sig_params, GenericsPosition::Child)
}; };
GenericsGenerationResults { GenericsGenerationResults {
@@ -296,6 +329,7 @@ fn uplift_delegation_generic_params(
&mut self, &mut self,
span: Span, span: Span,
params: &'hir [ty::GenericParamDef], params: &'hir [ty::GenericParamDef],
rename_self: bool,
) -> &'hir hir::Generics<'hir> { ) -> &'hir hir::Generics<'hir> {
let params = self.arena.alloc_from_iter(params.iter().map(|p| { let params = self.arena.alloc_from_iter(params.iter().map(|p| {
let def_kind = match p.kind { let def_kind = match p.kind {
@@ -304,7 +338,20 @@ fn uplift_delegation_generic_params(
GenericParamDefKind::Const { .. } => DefKind::ConstParam, GenericParamDefKind::Const { .. } => DefKind::ConstParam,
}; };
let param_ident = Ident::new(p.name, span); // Rename Self generic param to This so it is properly propagated.
// If the user will create a function `fn foo<Self>() {}` with generic
// param "Self" then it will not be generated in HIR, the same thing
// applies to traits, `trait Trait<Self> {}` will be represented as
// `trait Trait {}` in HIR and "unexpected keyword `Self` in generic parameters"
// error will be emitted.
// Note that we do not rename `Self` to `This` after non-recursive reuse
// from Trait, in this case the `Self` should not be propagated
// (we rely that implicit `Self` generic param of a trait is named "Self")
// and it is OK to have Self generic param generated during lowering.
let param_name =
if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name };
let param_ident = Ident::new(param_name, span);
let def_name = Some(param_ident.name); let def_name = Some(param_ident.name);
let node_id = self.next_node_id(); let node_id = self.next_node_id();
@@ -396,6 +396,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
_ => EF_PPC64_ABI_UNKNOWN, _ => EF_PPC64_ABI_UNKNOWN,
} }
} }
Architecture::Sparc32Plus => elf::EF_SPARC_32PLUS,
_ => 0, _ => 0,
} }
} }
@@ -16,10 +16,7 @@
use hir::def::DefKind; use hir::def::DefKind;
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir::def_id::LocalDefIdMap; use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
use rustc_hir::definitions::{
DefPathData, PerParentDisambiguatorState, PerParentDisambiguatorsMap,
};
use rustc_hir::{self as hir}; use rustc_hir::{self as hir};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
@@ -108,7 +105,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
ecx: &mut InterpCx<'tcx, M>, ecx: &mut InterpCx<'tcx, M>,
alloc_id: AllocId, alloc_id: AllocId,
mutability: Mutability, mutability: Mutability,
disambiguators: Option<&mut LocalDefIdMap<PerParentDisambiguatorState>>, disambiguator: Option<&mut PerParentDisambiguatorState>,
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, InternError> { ) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, InternError> {
trace!("intern_shallow {:?}", alloc_id); trace!("intern_shallow {:?}", alloc_id);
// remove allocation // remove allocation
@@ -132,7 +129,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
static_id, static_id,
alloc_id, alloc_id,
alloc, alloc,
disambiguators.expect("disambiguators needed"), disambiguator.expect("disambiguator needed"),
); );
} else { } else {
ecx.tcx.set_alloc_id_memory(alloc_id, alloc); ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
@@ -147,19 +144,18 @@ fn intern_as_new_static<'tcx>(
static_id: LocalDefId, static_id: LocalDefId,
alloc_id: AllocId, alloc_id: AllocId,
alloc: ConstAllocation<'tcx>, alloc: ConstAllocation<'tcx>,
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>, disambiguator: &mut PerParentDisambiguatorState,
) { ) {
// `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`. // `intern_const_alloc_recursive` is called once per static and it contains the `PerParentDisambiguatorState`.
// The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the // The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
// `DisambiguatorState` ensures the generated path is unique for this call as we generate // `PerParentDisambiguatorState` ensures the generated path is unique for this call as we generate
// `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call. // `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
let feed = tcx.create_def( let feed = tcx.create_def(
static_id, static_id,
None, None,
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true }, DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
Some(DefPathData::NestedStatic), Some(DefPathData::NestedStatic),
//FIXME(oli-obk): cleanup (https://github.com/rust-lang/rust/pull/155547#discussion_r3110792640) disambiguator,
disambiguators.get_or_create(static_id),
); );
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
@@ -209,7 +205,9 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
intern_kind: InternKind, intern_kind: InternKind,
ret: &MPlaceTy<'tcx>, ret: &MPlaceTy<'tcx>,
) -> Result<(), InternError> { ) -> Result<(), InternError> {
let mut disambiguators = Default::default(); let mut disambiguator =
ecx.machine.static_def_id().map(|id| PerParentDisambiguatorState::new(id));
let mut disambiguator = disambiguator.as_mut();
// We are interning recursively, and for mutability we are distinguishing the "root" allocation // We are interning recursively, and for mutability we are distinguishing the "root" allocation
// that we are starting in, and all other allocations that we are encountering recursively. // that we are starting in, and all other allocations that we are encountering recursively.
@@ -248,13 +246,15 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
// This gives us the initial set of nested allocations, which will then all be processed // This gives us the initial set of nested allocations, which will then all be processed
// recursively in the loop below. // recursively in the loop below.
let mut todo: Vec<_> = if is_static { let mut todo: Vec<_> = if is_static {
assert!(disambiguator.is_some());
// Do not steal the root allocation, we need it later to create the return value of `eval_static_initializer`. // Do not steal the root allocation, we need it later to create the return value of `eval_static_initializer`.
// But still change its mutability to match the requested one. // But still change its mutability to match the requested one.
let (kind, alloc) = ecx.memory.alloc_map.get_mut(&base_alloc_id).unwrap(); let (kind, alloc) = ecx.memory.alloc_map.get_mut(&base_alloc_id).unwrap();
prepare_alloc(*ecx.tcx, *kind, alloc, base_mutability)?; prepare_alloc(*ecx.tcx, *kind, alloc, base_mutability)?;
alloc.provenance().ptrs().iter().map(|&(_, prov)| prov).collect() alloc.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
} else { } else {
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguators))?.collect() assert!(disambiguator.is_none());
intern_shallow(ecx, base_alloc_id, base_mutability, None)?.collect()
}; };
// We need to distinguish "has just been interned" from "was already in `tcx`", // We need to distinguish "has just been interned" from "was already in `tcx`",
// so we track this in a separate set. // so we track this in a separate set.
@@ -336,7 +336,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
// okay with losing some potential for immutability here. This can anyway only affect // okay with losing some potential for immutability here. This can anyway only affect
// `static mut`. // `static mut`.
just_interned.insert(alloc_id); just_interned.insert(alloc_id);
let next = intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguators))?; let next = intern_shallow(ecx, alloc_id, inner_mutability, disambiguator.as_deref_mut())?;
todo.extend(next); todo.extend(next);
} }
if found_bad_mutable_ptr { if found_bad_mutable_ptr {
@@ -50,11 +50,6 @@ pub enum PrintKind {
} }
impl PrintKind { impl PrintKind {
/// FIXME: rust-analyzer doesn't support `#![feature(macro_derive)]` yet
/// (<https://github.com/rust-lang/rust-analyzer/issues/21043>), which breaks autocomplete.
/// Work around that by aliasing the trait constant to a regular constant.
const ALL_VARIANTS: &[Self] = <Self as AllVariants>::ALL_VARIANTS;
fn name(self) -> &'static str { fn name(self) -> &'static str {
use PrintKind::*; use PrintKind::*;
match self { match self {
@@ -1,4 +1,6 @@
use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base}; use crate::spec::{
Arch, CfgAbi, FloatAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
};
pub(crate) fn target() -> Target { pub(crate) fn target() -> Target {
Target { Target {
@@ -24,6 +26,7 @@ pub(crate) fn target() -> Target {
// linker error, so set it to `true` here. // linker error, so set it to `true` here.
// FIXME(#146996): Remove this override once #146996 has been fixed. // FIXME(#146996): Remove this override once #146996 has been fixed.
default_uwtable: false, default_uwtable: false,
supported_sanitizers: SanitizerSet::ADDRESS,
..base::linux_gnu::opts() ..base::linux_gnu::opts()
}, },
} }
@@ -1,4 +1,6 @@
use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base}; use crate::spec::{
Arch, CfgAbi, FloatAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
};
// This target is for glibc Linux on ARMv7 without NEON or // This target is for glibc Linux on ARMv7 without NEON or
// thumb-mode. See the thumbv7neon variant for enabling both. // thumb-mode. See the thumbv7neon variant for enabling both.
@@ -23,6 +25,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(64), max_atomic_width: Some(64),
mcount: "\u{1}__gnu_mcount_nc".into(), mcount: "\u{1}__gnu_mcount_nc".into(),
llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
supported_sanitizers: SanitizerSet::ADDRESS,
..base::linux_gnu::opts() ..base::linux_gnu::opts()
}, },
} }
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
llvm_target: "thumbv7a-none-eabi".into(), llvm_target: "thumbv7a-none-eabi".into(),
metadata: TargetMetadata { metadata: TargetMetadata {
description: Some("Thumb-mode Bare Armv7-A".into()), description: Some("Thumb-mode Bare Armv7-A".into()),
tier: Some(2), tier: Some(3),
host_tools: Some(false), host_tools: Some(false),
std: Some(false), std: Some(false),
}, },
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
llvm_target: "thumbv7a-none-eabihf".into(), llvm_target: "thumbv7a-none-eabihf".into(),
metadata: TargetMetadata { metadata: TargetMetadata {
description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()), description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()),
tier: Some(2), tier: Some(3),
host_tools: Some(false), host_tools: Some(false),
std: Some(false), std: Some(false),
}, },
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
llvm_target: "thumbv7r-none-eabi".into(), llvm_target: "thumbv7r-none-eabi".into(),
metadata: TargetMetadata { metadata: TargetMetadata {
description: Some("Thumb-mode Bare Armv7-R".into()), description: Some("Thumb-mode Bare Armv7-R".into()),
tier: Some(2), tier: Some(3),
host_tools: Some(false), host_tools: Some(false),
std: Some(false), std: Some(false),
}, },
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
llvm_target: "thumbv7r-none-eabihf".into(), llvm_target: "thumbv7r-none-eabihf".into(),
metadata: TargetMetadata { metadata: TargetMetadata {
description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()), description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()),
tier: Some(2), tier: Some(3),
host_tools: Some(false), host_tools: Some(false),
std: Some(false), std: Some(false),
}, },
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
llvm_target: "thumbv8r-none-eabihf".into(), llvm_target: "thumbv8r-none-eabihf".into(),
metadata: TargetMetadata { metadata: TargetMetadata {
description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()), description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()),
tier: Some(2), tier: Some(3),
host_tools: Some(false), host_tools: Some(false),
std: Some(false), std: Some(false),
}, },
@@ -10,7 +10,7 @@
//! those target flags doesn't automatically rebuild libcore / liballoc with //! those target flags doesn't automatically rebuild libcore / liballoc with
//! them, and in order to get those libraries rebuilt you need to use the //! them, and in order to get those libraries rebuilt you need to use the
//! nightly Rust feature `-Zbuild-std`. This target is for people who want to //! nightly Rust feature `-Zbuild-std`. This target is for people who want to
//! use stable Rust, and target a stable set pf WebAssembly features. //! use stable Rust, and target a stable set of WebAssembly features.
use crate::spec::{Arch, Cc, LinkerFlavor, Os, Target, TargetMetadata, base}; use crate::spec::{Arch, Cc, LinkerFlavor, Os, Target, TargetMetadata, base};
@@ -363,6 +363,7 @@ pub(super) fn maybe_report_ambiguity(
if impl_candidates.len() < 40 { if impl_candidates.len() < 40 {
self.report_similar_impl_candidates( self.report_similar_impl_candidates(
impl_candidates.as_slice(), impl_candidates.as_slice(),
obligation,
trait_pred, trait_pred,
obligation.cause.body_id, obligation.cause.body_id,
&mut err, &mut err,
@@ -1973,6 +1973,7 @@ pub(super) fn find_similar_impl_candidates(
pub(super) fn report_similar_impl_candidates( pub(super) fn report_similar_impl_candidates(
&self, &self,
impl_candidates: &[ImplCandidate<'tcx>], impl_candidates: &[ImplCandidate<'tcx>],
obligation: &PredicateObligation<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
body_def_id: LocalDefId, body_def_id: LocalDefId,
err: &mut Diag<'_>, err: &mut Diag<'_>,
@@ -2037,6 +2038,20 @@ pub(super) fn report_similar_impl_candidates(
}; };
if let [single] = &impl_candidates { if let [single] = &impl_candidates {
let self_ty = trait_pred.skip_binder().self_ty();
if !self_ty.has_escaping_bound_vars() {
let self_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
if let ty::Ref(_, inner_ty, _) = self_ty.kind()
&& self.can_eq(param_env, single.trait_ref.self_ty(), *inner_ty)
&& !self.where_clause_expr_matches_failed_self_ty(obligation, self_ty)
{
// Avoid pointing at a nearby impl like `String: Borrow<str>` when the
// failing obligation comes from something nested inside an enclosing call
// expression such as `foo(&[String::from("a")])`.
return true;
}
}
// If we have a single implementation, try to unify it with the trait ref // If we have a single implementation, try to unify it with the trait ref
// that failed. This should uncover a better hint for what *is* implemented. // that failed. This should uncover a better hint for what *is* implemented.
if self.probe(|_| { if self.probe(|_| {
@@ -2456,6 +2471,7 @@ fn report_similar_impl_candidates_for_root_obligation(
let impl_candidates = self.find_similar_impl_candidates(trait_pred); let impl_candidates = self.find_similar_impl_candidates(trait_pred);
self.report_similar_impl_candidates( self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
obligation,
trait_pred, trait_pred,
body_def_id, body_def_id,
err, err,
@@ -3137,6 +3153,7 @@ fn try_to_add_help_message(
let impl_candidates = self.find_similar_impl_candidates(trait_predicate); let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates( if !self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
obligation,
trait_predicate, trait_predicate,
body_def_id, body_def_id,
err, err,
@@ -1584,6 +1584,39 @@ pub fn extract_callable_info(
if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) } if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
} }
pub(super) fn where_clause_expr_matches_failed_self_ty(
&self,
obligation: &PredicateObligation<'tcx>,
old_self_ty: Ty<'tcx>,
) -> bool {
let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code() else {
return true;
};
let (Some(typeck_results), Some(body)) = (
self.typeck_results.as_ref(),
self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id),
) else {
return true;
};
let mut expr_finder = FindExprBySpan::new(obligation.cause.span, self.tcx);
expr_finder.visit_expr(body.value);
let Some(expr) = expr_finder.result else {
return true;
};
let inner_old_self_ty = match old_self_ty.kind() {
ty::Ref(_, inner_ty, _) => Some(*inner_ty),
_ => None,
};
[typeck_results.expr_ty_adjusted_opt(expr)].into_iter().flatten().any(|expr_ty| {
self.can_eq(obligation.param_env, expr_ty, old_self_ty)
|| inner_old_self_ty
.is_some_and(|inner_ty| self.can_eq(obligation.param_env, expr_ty, inner_ty))
})
}
pub(super) fn suggest_add_reference_to_arg( pub(super) fn suggest_add_reference_to_arg(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
@@ -1857,6 +1890,15 @@ pub(super) fn suggest_add_reference_to_arg(
if let hir::ExprKind::AddrOf(_, _, _) = expr.kind { if let hir::ExprKind::AddrOf(_, _, _) = expr.kind {
return false; return false;
} }
let old_self_ty = old_pred.skip_binder().self_ty();
if !old_self_ty.has_escaping_bound_vars()
&& !self.where_clause_expr_matches_failed_self_ty(
obligation,
self.tcx.instantiate_bound_regions_with_erased(old_pred.self_ty()),
)
{
return false;
}
let needs_parens_post = expr_needs_parens(expr); let needs_parens_post = expr_needs_parens(expr);
let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) { let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) {
Node::Expr(e) Node::Expr(e)
+11 -13
View File
@@ -1,8 +1,6 @@
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::{ use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
DefPathData, PerParentDisambiguatorState, PerParentDisambiguatorsMap,
};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, ConstItemRhs, ImplItemImplKind, ItemKind}; use rustc_hir::{self as hir, ConstItemRhs, ImplItemImplKind, ItemKind};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
@@ -131,7 +129,7 @@ struct RPITVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
synthetics: Vec<LocalDefId>, synthetics: Vec<LocalDefId>,
data: DefPathData, data: DefPathData,
disambiguators: &'a mut LocalDefIdMap<PerParentDisambiguatorState>, disambiguator: &'a mut PerParentDisambiguatorState,
} }
impl<'tcx> Visitor<'tcx> for RPITVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for RPITVisitor<'_, 'tcx> {
@@ -140,7 +138,7 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result
self.tcx, self.tcx,
opaque.def_id, opaque.def_id,
self.data, self.data,
&mut self.disambiguators, &mut self.disambiguator,
)); ));
intravisit::walk_opaque_ty(self, opaque) intravisit::walk_opaque_ty(self, opaque)
} }
@@ -151,7 +149,7 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
def_id: LocalDefId, def_id: LocalDefId,
) -> DefIdMap<Vec<DefId>> { ) -> DefIdMap<Vec<DefId>> {
let item = tcx.hir_expect_item(def_id); let item = tcx.hir_expect_item(def_id);
let disambiguators = &mut Default::default(); let disambiguator = &mut PerParentDisambiguatorState::new(def_id);
match item.kind { match item.kind {
ItemKind::Trait(.., trait_item_refs) => trait_item_refs ItemKind::Trait(.., trait_item_refs) => trait_item_refs
.iter() .iter()
@@ -165,7 +163,7 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
}; };
let def_name = tcx.item_name(fn_def_id.to_def_id()); let def_name = tcx.item_name(fn_def_id.to_def_id());
let data = DefPathData::AnonAssocTy(def_name); let data = DefPathData::AnonAssocTy(def_name);
let mut visitor = RPITVisitor { tcx, synthetics: vec![], data, disambiguators }; let mut visitor = RPITVisitor { tcx, synthetics: vec![], data, disambiguator };
visitor.visit_fn_ret_ty(output); visitor.visit_fn_ret_ty(output);
let defs = visitor let defs = visitor
.synthetics .synthetics
@@ -199,7 +197,7 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
return Some((did, vec![])); return Some((did, vec![]));
}; };
let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| { let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| {
associated_type_for_impl_trait_in_impl(tcx, id, item, disambiguators) associated_type_for_impl_trait_in_impl(tcx, id, item, disambiguator)
.to_def_id() .to_def_id()
}); });
Some((did, iter.collect())) Some((did, iter.collect()))
@@ -223,7 +221,7 @@ fn associated_type_for_impl_trait_in_trait(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
opaque_ty_def_id: LocalDefId, opaque_ty_def_id: LocalDefId,
data: DefPathData, data: DefPathData,
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>, disambiguator: &mut PerParentDisambiguatorState,
) -> LocalDefId { ) -> LocalDefId {
let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) = | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) =
@@ -242,7 +240,7 @@ fn associated_type_for_impl_trait_in_trait(
None, None,
DefKind::AssocTy, DefKind::AssocTy,
Some(data), Some(data),
disambiguators.get_or_create(trait_def_id), disambiguator,
); );
let local_def_id = trait_assoc_ty.def_id(); let local_def_id = trait_assoc_ty.def_id();
@@ -285,7 +283,7 @@ fn associated_type_for_impl_trait_in_impl(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
trait_assoc_def_id: DefId, trait_assoc_def_id: DefId,
impl_fn: &hir::ImplItem<'_>, impl_fn: &hir::ImplItem<'_>,
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>, disambiguator: &mut PerParentDisambiguatorState,
) -> LocalDefId { ) -> LocalDefId {
let impl_local_def_id = tcx.local_parent(impl_fn.owner_id.def_id); let impl_local_def_id = tcx.local_parent(impl_fn.owner_id.def_id);
@@ -308,7 +306,7 @@ fn associated_type_for_impl_trait_in_impl(
None, None,
DefKind::AssocTy, DefKind::AssocTy,
Some(data), Some(data),
disambiguators.get_or_create(impl_local_def_id), disambiguator,
); );
let local_def_id = impl_assoc_ty.def_id(); let local_def_id = impl_assoc_ty.def_id();
+1 -1
View File
@@ -11,7 +11,7 @@
//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], //! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
//! but should be implemented when the conversion can fail. //! but should be implemented when the conversion can fail.
//! //!
//! The traits in this module are often used as trait bounds for generic functions such that to //! The traits in this module are often used as trait bounds for generic functions such that
//! arguments of multiple types are supported. See the documentation of each trait for examples. //! arguments of multiple types are supported. See the documentation of each trait for examples.
//! //!
//! As a library author, you should always prefer implementing [`From<T>`][`From`] or //! As a library author, you should always prefer implementing [`From<T>`][`From`] or
+1
View File
@@ -131,6 +131,7 @@
/// [`read`]: File::read /// [`read`]: File::read
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "File")] #[cfg_attr(not(test), rustc_diagnostic_item = "File")]
#[diagnostic::on_move(note = "you can use `File::try_clone` to duplicate a `File` instance")]
pub struct File { pub struct File {
inner: fs_imp::File, inner: fs_imp::File,
} }
+1
View File
@@ -278,6 +278,7 @@
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(deprecated_suggestion)] #![feature(deprecated_suggestion)]
#![feature(diagnostic_on_move)]
#![feature(doc_cfg)] #![feature(doc_cfg)]
#![feature(doc_masked)] #![feature(doc_masked)]
#![feature(doc_notable_trait)] #![feature(doc_notable_trait)]
@@ -0,0 +1,92 @@
# `diagnostic_on_move`
The tracking issue for this feature is: [#154181]
------------------------
The `diagnostic_on_move` feature allows use of the `#[diagnostic::on_move]` attribute. It should be
placed on struct, enum and union declarations, though it is not an error to be located in other
positions. This attribute is a hint to the compiler to supplement the error message when the
annotated type is involved in a borrowcheck error.
For example, [`File`] is annotated as such:
```rust
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(note = "you can use `File::try_clone` \
to duplicate a `File` instance")]
pub struct File {
// ...
}
```
When you try to use a `File` after it's already been moved, it will helpfully tell you about `try_clone`.
The message and label can also be customized:
```rust
#![feature(diagnostic_on_move)]
use std::marker::PhantomData;
#[diagnostic::on_move(
message = "`{Self}` cannot be used multiple times",
label = "this token may only be used once",
note = "you can create a new `Token` with `Token::conjure()`"
)]
pub struct Token<'brand> {
spooky: PhantomData<&'brand ()>,
}
impl Token<'_> {
pub fn conjure<'u>() -> Token<'u> {
Token {
spooky: PhantomData,
}
}
}
```
The user may try to use it like this:
```rust,compile_fail,E0382
# #![feature(diagnostic_on_move)]
#
# use std::marker::PhantomData;
#
# #[diagnostic::on_move(
# message = "`{Self}` cannot be used multiple times",
# label = "this token may only be used once",
# note = "you can create a new `Token` with `Token::conjure()`"
# )]
# pub struct Token<'brand> {
# spooky: PhantomData<&'brand ()>,
# }
#
# impl Token<'_> {
# pub fn conjure<'u>() -> Token<'u> {
# Token {
# spooky: PhantomData,
# }
# }
# }
# fn main() {
let token = Token::conjure();
let _ = (token, token);
# }
```
This will result in the following error:
```text
error[E0382]: `Token` cannot be used multiple times
--> src/main.rs:24:21
|
1 | let token = Token::conjure();
| ----- this token may only be used once
2 | let _ = (token, token);
| ----- ^^^^^ value used here after move
| |
| value moved here
|
= note: you can create a new `Token` with `Token::conjure()`
```
[`File`]: https://doc.rust-lang.org/nightly/std/fs/struct.File.html "File in std::fs"
[#154181]: https://github.com/rust-lang/rust/issues/154181 "Tracking Issue for #[diagnostic::on_move]"
+2 -2
View File
@@ -516,7 +516,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> {
Managarm => "Managarm", Managarm => "Managarm",
Motor => "Motor OS", Motor => "Motor OS",
NetBsd => "NetBSD", NetBsd => "NetBSD",
None => "bare-metal", // FIXME(scrabsha): is this appropriate? None => "bare-metal",
Nto => "QNX Neutrino", Nto => "QNX Neutrino",
NuttX => "NuttX", NuttX => "NuttX",
OpenBsd => "OpenBSD", OpenBsd => "OpenBSD",
@@ -593,7 +593,7 @@ fn human_readable_target_env(env: Symbol) -> Option<&'static str> {
// tidy-alphabetical-start // tidy-alphabetical-start
Gnu => "GNU", Gnu => "GNU",
MacAbi => "Catalyst", MacAbi => "Catalyst",
Mlibc => "mac ABI", Mlibc => "Managarm C Library",
Msvc => "MSVC", Msvc => "MSVC",
Musl => "musl", Musl => "musl",
Newlib => "Newlib", Newlib => "Newlib",
+6 -17
View File
@@ -15,9 +15,7 @@
use crate::fold::DocFolder; use crate::fold::DocFolder;
use crate::formats::Impl; use crate::formats::Impl;
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::markdown::short_markdown_summary; use crate::html::render::{IndexItem, IndexItemInfo};
use crate::html::render::IndexItem;
use crate::html::render::search_index::get_function_type_for_search;
use crate::visit_lib::RustdocEffectiveVisibilities; use crate::visit_lib::RustdocEffectiveVisibilities;
/// This cache is used to store information about the [`clean::Crate`] being /// This cache is used to store information about the [`clean::Crate`] being
@@ -580,7 +578,6 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
debug_assert!(!item.is_stripped()); debug_assert!(!item.is_stripped());
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
// For searching purposes, a re-export is a duplicate if: // For searching purposes, a re-export is a duplicate if:
// //
// - It's either an inline, or a true re-export // - It's either an inline, or a true re-export
@@ -591,32 +588,24 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
_ => item_def_id, _ => item_def_id,
}; };
let (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id(); let (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id();
let search_type = get_function_type_for_search( let info = IndexItemInfo::new(
item,
tcx, tcx,
clean_impl_generics(cache.parent_stack.last()).as_ref(),
parent_did,
cache, cache,
item,
parent_did,
clean_impl_generics(cache.parent_stack.last()).as_ref(),
); );
let aliases = item.attrs.get_doc_aliases();
let is_deprecated = item.is_deprecated(tcx);
let is_unstable = item.is_unstable();
let index_item = IndexItem { let index_item = IndexItem {
ty: item.type_(),
defid: Some(defid), defid: Some(defid),
name, name,
module_path: parent_path.to_vec(), module_path: parent_path.to_vec(),
desc,
parent: parent_did, parent: parent_did,
parent_idx: None, parent_idx: None,
trait_parent, trait_parent,
trait_parent_idx: None, trait_parent_idx: None,
exact_module_path: None, exact_module_path: None,
impl_id, impl_id,
search_type, info,
aliases,
is_deprecated,
is_unstable,
}; };
cache.search_index.push(index_item); cache.search_index.push(index_item);
+32 -8
View File
@@ -66,7 +66,7 @@
pub(crate) use self::context::*; pub(crate) use self::context::*;
pub(crate) use self::span_map::{LinkFromSrc, collect_spans_and_sources}; pub(crate) use self::span_map::{LinkFromSrc, collect_spans_and_sources};
pub(crate) use self::write_shared::*; pub(crate) use self::write_shared::*;
use crate::clean::{self, Defaultness, ItemId, RenderedLink}; use crate::clean::{self, Defaultness, Item, ItemId, RenderedLink};
use crate::display::{Joined as _, MaybeDisplay as _}; use crate::display::{Joined as _, MaybeDisplay as _};
use crate::error::Error; use crate::error::Error;
use crate::formats::Impl; use crate::formats::Impl;
@@ -79,8 +79,9 @@
print_type, print_where_clause, visibility_print_with_space, print_type, print_where_clause, visibility_print_with_space,
}; };
use crate::html::markdown::{ use crate::html::markdown::{
HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, short_markdown_summary,
}; };
use crate::html::render::search_index::get_function_type_for_search;
use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD; use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD;
use crate::html::{highlight, sources}; use crate::html::{highlight, sources};
use crate::scrape_examples::{CallData, CallLocation}; use crate::scrape_examples::{CallData, CallLocation};
@@ -124,25 +125,48 @@ enum RenderMode {
// Helper structs for rendering items/sidebars and carrying along contextual // Helper structs for rendering items/sidebars and carrying along contextual
// information // information
#[derive(Debug)]
pub(crate) struct IndexItemInfo {
pub(crate) ty: ItemType,
pub(crate) desc: String,
pub(crate) search_type: Option<IndexItemFunctionType>,
pub(crate) aliases: Box<[Symbol]>,
pub(crate) deprecation: Option<Deprecation>,
pub(crate) is_unstable: bool,
}
impl IndexItemInfo {
pub(crate) fn new(
tcx: TyCtxt<'_>,
cache: &Cache,
item: &Item,
parent_did: Option<DefId>,
impl_generics: Option<&(clean::Type, clean::Generics)>,
) -> Self {
let ty = item.type_();
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
let search_type = get_function_type_for_search(item, tcx, impl_generics, parent_did, cache);
let aliases = item.attrs.get_doc_aliases();
let deprecation = item.deprecation(tcx);
let is_unstable = item.is_unstable();
Self { ty, desc, search_type, aliases, deprecation, is_unstable }
}
}
/// Struct representing one entry in the JS search index. These are all emitted /// Struct representing one entry in the JS search index. These are all emitted
/// by hand to a large JS file at the end of cache-creation. /// by hand to a large JS file at the end of cache-creation.
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct IndexItem { pub(crate) struct IndexItem {
pub(crate) ty: ItemType,
pub(crate) defid: Option<DefId>, pub(crate) defid: Option<DefId>,
pub(crate) name: Symbol, pub(crate) name: Symbol,
pub(crate) module_path: Vec<Symbol>, pub(crate) module_path: Vec<Symbol>,
pub(crate) desc: String,
pub(crate) parent: Option<DefId>, pub(crate) parent: Option<DefId>,
pub(crate) parent_idx: Option<usize>, pub(crate) parent_idx: Option<usize>,
pub(crate) trait_parent: Option<DefId>, pub(crate) trait_parent: Option<DefId>,
pub(crate) trait_parent_idx: Option<usize>, pub(crate) trait_parent_idx: Option<usize>,
pub(crate) exact_module_path: Option<Vec<Symbol>>, pub(crate) exact_module_path: Option<Vec<Symbol>>,
pub(crate) impl_id: Option<DefId>, pub(crate) impl_id: Option<DefId>,
pub(crate) search_type: Option<IndexItemFunctionType>, pub(crate) info: IndexItemInfo,
pub(crate) aliases: Box<[Symbol]>,
pub(crate) is_deprecated: bool,
pub(crate) is_unstable: bool,
} }
/// A type used for the search index. /// A type used for the search index.
+26 -32
View File
@@ -13,7 +13,7 @@
use rustc_ast::join_path_syms; use rustc_ast::join_path_syms;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
use rustc_hir::find_attr; use rustc_hir::find_attr;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
@@ -29,7 +29,9 @@
use crate::formats::cache::{Cache, OrphanImplItem}; use crate::formats::cache::{Cache, OrphanImplItem};
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::markdown::short_markdown_summary; use crate::html::markdown::short_markdown_summary;
use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; use crate::html::render::{
self, IndexItem, IndexItemFunctionType, IndexItemInfo, RenderType, RenderTypeId,
};
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub(crate) struct SerializedSearchIndex { pub(crate) struct SerializedSearchIndex {
@@ -1270,29 +1272,18 @@ pub(crate) fn build_index(
&cache.orphan_impl_items &cache.orphan_impl_items
{ {
if let Some((fqp, _)) = cache.paths.get(&parent) { if let Some((fqp, _)) = cache.paths.get(&parent) {
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); let info = IndexItemInfo::new(tcx, cache, item, Some(parent), impl_generics.as_ref());
search_index.push(IndexItem { search_index.push(IndexItem {
ty: item.type_(),
defid: item.item_id.as_def_id(), defid: item.item_id.as_def_id(),
name: item.name.unwrap(), name: item.name.unwrap(),
module_path: fqp[..fqp.len() - 1].to_vec(), module_path: fqp[..fqp.len() - 1].to_vec(),
desc,
parent: Some(parent), parent: Some(parent),
parent_idx: None, parent_idx: None,
trait_parent, trait_parent,
trait_parent_idx: None, trait_parent_idx: None,
exact_module_path: None, exact_module_path: None,
impl_id, impl_id,
search_type: get_function_type_for_search( info,
item,
tcx,
impl_generics.as_ref(),
Some(parent),
cache,
),
aliases: item.attrs.get_doc_aliases(),
is_deprecated: item.is_deprecated(tcx),
is_unstable: item.is_unstable(),
}); });
} }
} }
@@ -1301,11 +1292,10 @@ pub(crate) fn build_index(
search_index.sort_unstable_by(|k1, k2| { search_index.sort_unstable_by(|k1, k2| {
// `sort_unstable_by_key` produces lifetime errors // `sort_unstable_by_key` produces lifetime errors
// HACK(rustdoc): should not be sorting `CrateNum` or `DefIndex`, this will soon go away, too // HACK(rustdoc): should not be sorting `CrateNum` or `DefIndex`, this will soon go away, too
let k1 = fn key(i: &IndexItem) -> (&[Symbol], &str, ItemType, Option<(DefIndex, CrateNum)>) {
(&k1.module_path, k1.name.as_str(), &k1.ty, k1.parent.map(|id| (id.index, id.krate))); (&i.module_path, i.name.as_str(), i.info.ty, i.parent.map(|id| (id.index, id.krate)))
let k2 = }
(&k2.module_path, k2.name.as_str(), &k2.ty, k2.parent.map(|id| (id.index, id.krate))); Ord::cmp(&key(k1), &key(k2))
Ord::cmp(&k1, &k2)
}); });
// Now, convert to an on-disk search index format // Now, convert to an on-disk search index format
@@ -1466,7 +1456,7 @@ pub(crate) fn build_index(
if fqp.last() != Some(&item.name) { if fqp.last() != Some(&item.name) {
return None; return None;
} }
let path = if item.ty == ItemType::Macro let path = if item.info.ty == ItemType::Macro
&& find_attr!(tcx, defid, MacroExport { .. }) && find_attr!(tcx, defid, MacroExport { .. })
{ {
// `#[macro_export]` always exports to the crate root. // `#[macro_export]` always exports to the crate root.
@@ -1501,8 +1491,9 @@ pub(crate) fn build_index(
if item.impl_id.is_some() if item.impl_id.is_some()
&& let Some(parent_idx) = item.parent_idx && let Some(parent_idx) = item.parent_idx
{ {
let count = let count = associated_item_duplicates
associated_item_duplicates.entry((parent_idx, item.ty, item.name)).or_insert(0); .entry((parent_idx, item.info.ty, item.name))
.or_insert(0);
*count += 1; *count += 1;
} }
} }
@@ -1525,24 +1516,27 @@ pub(crate) fn build_index(
let new_entry_id = serialized_index.add_entry( let new_entry_id = serialized_index.add_entry(
item.name, item.name,
EntryData { EntryData {
ty: item.ty, ty: item.info.ty,
parent: item.parent_idx, parent: item.parent_idx,
trait_parent: item.trait_parent_idx, trait_parent: item.trait_parent_idx,
module_path, module_path,
exact_module_path, exact_module_path,
deprecated: item.is_deprecated, deprecated: item
unstable: item.is_unstable, .info
.deprecation
.is_some_and(|deprecation| deprecation.is_in_effect()),
unstable: item.info.is_unstable,
associated_item_disambiguator_or_extern_crate_url: if let Some(impl_id) = associated_item_disambiguator_or_extern_crate_url: if let Some(impl_id) =
item.impl_id item.impl_id
&& let Some(parent_idx) = item.parent_idx && let Some(parent_idx) = item.parent_idx
&& associated_item_duplicates && associated_item_duplicates
.get(&(parent_idx, item.ty, item.name)) .get(&(parent_idx, item.info.ty, item.name))
.copied() .copied()
.unwrap_or(0) .unwrap_or(0)
> 1 > 1
{ {
Some(render::get_id_for_impl(tcx, ItemId::DefId(impl_id))) Some(render::get_id_for_impl(tcx, ItemId::DefId(impl_id)))
} else if item.ty == ItemType::ExternCrate } else if item.info.ty == ItemType::ExternCrate
&& let Some(local_def_id) = item.defid.and_then(|def_id| def_id.as_local()) && let Some(local_def_id) = item.defid.and_then(|def_id| def_id.as_local())
&& let cnum = tcx.extern_mod_stmt_cnum(local_def_id).unwrap_or(LOCAL_CRATE) && let cnum = tcx.extern_mod_stmt_cnum(local_def_id).unwrap_or(LOCAL_CRATE)
&& let Some(ExternalLocation::Remote { url, is_absolute }) = && let Some(ExternalLocation::Remote { url, is_absolute }) =
@@ -1555,12 +1549,12 @@ pub(crate) fn build_index(
}, },
krate: crate_idx, krate: crate_idx,
}, },
item.desc.to_string(), item.info.desc.to_string(),
); );
// Aliases // Aliases
// ------- // -------
for alias in &item.aliases[..] { for alias in &item.info.aliases {
serialized_index.push_alias(alias.as_str().to_string(), new_entry_id); serialized_index.push_alias(alias.as_str().to_string(), new_entry_id);
} }
@@ -1833,7 +1827,7 @@ fn convert_render_type(
_ => {} _ => {}
} }
} }
if let Some(search_type) = &mut item.search_type { if let Some(search_type) = &mut item.info.search_type {
let mut used_in_function_inputs = BTreeSet::new(); let mut used_in_function_inputs = BTreeSet::new();
let mut used_in_function_output = BTreeSet::new(); let mut used_in_function_output = BTreeSet::new();
for item in &mut search_type.inputs { for item in &mut search_type.inputs {
@@ -1900,7 +1894,7 @@ fn convert_render_type(
// The number 8 is arbitrary. We want it big, but not enormous, // The number 8 is arbitrary. We want it big, but not enormous,
// because the postings list has to fill in an empty array for each // because the postings list has to fill in an empty array for each
// unoccupied size. // unoccupied size.
if item.ty.is_fn_like() { 0 } else { 16 }; if item.info.ty.is_fn_like() { 0 } else { 16 };
serialized_index.function_data[new_entry_id] = Some(search_type.clone()); serialized_index.function_data[new_entry_id] = Some(search_type.clone());
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
+55
View File
@@ -0,0 +1,55 @@
#![attr = Feature([fn_delegation#0])]
extern crate std;
#[attr = PreludeImport]
use ::std::prelude::rust_2015::*;
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:delegation-self-rename.pp
trait Trait<'a, A, const B: bool> {
fn foo<'b, const B2: bool, T, U,
impl FnOnce() -> usize>(&self, f: impl FnOnce() -> usize) -> usize
where impl FnOnce() -> usize: FnOnce() -> usize { f() + 1 }
}
struct X;
impl <'a, A, const B: bool> Trait<'a, A, B> for X { }
#[attr = Inline(Hint)]
fn foo<'a, Self, A, const B: _, const B2: _, T, U,
impl FnOnce() -> usize>(self: _, arg1: _) -> _ where
'a:'a { self.foo::<B2, T, U>(arg1) }
#[attr = Inline(Hint)]
fn bar<Self, impl FnOnce() -> usize>(self: _, arg1: _)
-> _ { Trait::<'static, (), true>::foo::<true, (), ()>(self, arg1) }
#[attr = Inline(Hint)]
fn foo2<'a, This, A, const B: _, const B2: _, T, U,
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
'a:'a { foo::<This, A, B, B2, T, U>(arg0, arg1) }
#[attr = Inline(Hint)]
fn bar2<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
-> _ { bar::<This>(arg0, arg1) }
trait Trait2 {
#[attr = Inline(Hint)]
fn foo3<'a, This, A, const B: _, const B2: _, T, U,
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
'a:'a { foo2::<This, A, B, B2, T, U>(arg0, arg1) }
#[attr = Inline(Hint)]
fn bar3<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
-> _ { bar2::<This>(arg0, arg1) }
}
impl Trait2 for () { }
#[attr = Inline(Hint)]
fn foo4<'a, This, A, const B: _, const B2: _, T, U,
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
'a:'a { <() as Trait2>::foo3::<This, A, B, B2, T, U>(arg0, arg1) }
#[attr = Inline(Hint)]
fn bar4<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
-> _ { <() as Trait2>::bar3::<This>(arg0, arg1) }
fn main() { }
+32
View File
@@ -0,0 +1,32 @@
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:delegation-self-rename.pp
#![feature(fn_delegation)]
trait Trait<'a, A, const B: bool> {
fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
f() + 1
}
}
struct X;
impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
reuse Trait::foo;
reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
reuse foo as foo2;
reuse bar as bar2;
trait Trait2 {
reuse foo2 as foo3;
reuse bar2 as bar3;
}
impl Trait2 for () {}
reuse <() as Trait2>::foo3 as foo4;
reuse <() as Trait2>::bar3 as bar4;
fn main() {}
+1 -1
View File
@@ -2,7 +2,7 @@
//@ has all_targets/fn.foo.html \ //@ has all_targets/fn.foo.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
// 'Available on GNU or Catalyst or mac ABI or MSVC or musl or Newlib or \ // 'Available on GNU or Catalyst or Managarm C Library or MSVC or musl or Newlib or \
// Neutrino 7.0 or Neutrino 7.1 or Neutrino 7.1 with io-sock or Neutrino 8.0 or \ // Neutrino 7.0 or Neutrino 7.1 or Neutrino 7.1 with io-sock or Neutrino 8.0 or \
// OpenHarmony or relibc or SGX or Simulator or WASIp1 or WASIp2 or WASIp3 or \ // OpenHarmony or relibc or SGX or Simulator or WASIp1 or WASIp2 or WASIp3 or \
// uClibc or V5 or target_env=fake_env only.' // uClibc or V5 or target_env=fake_env only.'
@@ -0,0 +1,59 @@
// Regression test for https://github.com/rust-lang/rust/issues/150898
//
// This test fails on Apple platforms with versions containing an allocator
// bug. If this fails with SIGABRT, you may need to upgrade your system to
// avoid other unexpected behavior.
//
// Note that the failure is non-deterministic so this test may pass even in
// conditions where the bug is present. That being said, on the author's
// machine this has a 100% rate of hitting the crash on at least a couple
// threads.
//
// The bug was resolved by macOS 26.4.
//@ run-pass
//@ only-aarch64-apple-darwin
//@ compile-flags: -C opt-level=1 -C codegen-units=1
use std::thread;
fn main() {
// Running with multiple threads substantially increases the change of
// hitting the bug.
thread::scope(|s| {
for _ in 0..10 {
s.spawn(run);
}
});
}
fn run() {
// This doesn't always fail, so rerun a few times
for _ in 0..100 {
unsafe {
core::arch::asm!(
"
// Alloc 18 bytes
mov x0, #18
bl _malloc
// Save the pointer to x21
mov x21, x0
// Alloc 18 bytes again
mov x0, #18
bl _malloc
// Store the contents of `x13` to the second allocation. `x13` is the
// magic register to cause the crash, other registers work well.
str x13, [x0]
// Free the pointers
bl _free
mov x0, x21
bl _free
",
out("x0") _,
out("x13") _,
out("x21") _,
clobber_abi("C"),
)
}
}
}
@@ -0,0 +1,45 @@
//@ run-pass
#![feature(fn_delegation)]
trait Trait<'a, A, const B: bool> {
fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
f() + 1
}
}
struct X;
impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
reuse Trait::foo;
reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
reuse foo as foo2;
reuse bar as bar2;
trait Trait2 {
reuse foo2 as foo3;
reuse bar2 as bar3;
}
impl Trait2 for () {}
reuse <() as Trait2>::foo3 as foo4;
reuse <() as Trait2>::bar3 as bar4;
fn main() {
assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
assert_eq!(foo2::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
assert_eq!(<()>::foo3::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
assert_eq!(foo4::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
assert_eq!(bar::<X>(&X, || 123), 124);
assert_eq!(bar2::<X>(&X, || 123), 124);
assert_eq!(<()>::bar3::<X>(&X, || 123), 124);
assert_eq!(bar4::<X>(&X, || 123), 124);
assert_eq!(bar(&X, || 123), 124);
assert_eq!(bar2(&X, || 123), 124);
assert_eq!(<()>::bar3(&X, || 123), 124);
assert_eq!(bar4::<X>(&X, || 123), 124);
}
@@ -62,40 +62,49 @@ pub fn check() {
} }
} }
// FIXME(fn_delegation): rename Self generic param in recursive delegations // Test recursive delegation through trait
// mod test_4 { mod test_4 {
// trait Trait<'a, A, const B: bool> { trait Trait<'a, A, const B: bool> {
// fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize { fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
// f() f()
// } }
// } }
// struct X; struct X;
// impl<'a, A, const B: bool> Trait<'a, A, B> for X {} impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
// reuse Trait::foo; reuse Trait::foo;
// reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar; reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
// trait Trait2 { trait Trait2 {
// reuse foo; reuse foo;
// reuse bar; reuse bar;
// } }
// reuse Trait2::foo as foo2; impl Trait2 for () {}
// reuse Trait2::foo::<'static, X, (), true, false, (), ()> as foo3;
// reuse Trait2::bar as bar2;
// reuse Trait2::bar::<X> as bar3;
// pub fn check() { reuse <() as Trait2>::foo as foo2;
// assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 123); reuse <() as Trait2>::foo::<'static, X, (), true, false, (), ()> as foo3;
// assert_eq!(bar::<X>(&X, || 123), 123); reuse <() as Trait2>::bar as bar2;
// assert_eq!(bar(&X, || 123), 123); reuse <() as Trait2>::bar::<X> as bar3;
// }
// } pub fn check() {
assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 123);
assert_eq!(bar::<X>(&X, || 123), 123);
assert_eq!(bar(&X, || 123), 123);
assert_eq!(foo2::<'static, X, (), true, false, (), ()>(&X, || 123), 123);
assert_eq!(bar2::<X>(&X, || 123), 123);
assert_eq!(bar2(&X, || 123), 123);
assert_eq!(foo3(&X, || 123), 123);
assert_eq!(bar3(&X, || 123), 123);
}
}
fn main() { fn main() {
test_1::check(); test_1::check();
test_2::check(); test_2::check();
test_3::check(); test_3::check();
// test_4::check(); test_4::check();
} }
@@ -0,0 +1,25 @@
//@ dont-require-annotations: NOTE
use std::fs::File;
use std::sync::Arc;
use std::rc::Rc;
fn main(){
let file = File::open("foo.txt").unwrap();
(file, file);
//~^ ERROR use of moved value: `file`
//~| NOTE you can use `File::try_clone` to duplicate a `File` instance
let arc = Arc::new(42);
//~^ NOTE this move could be avoided by cloning the original `Arc`, which is inexpensive
(arc, arc);
//~^ ERROR the type `Arc` does not implement `Copy`
//~| NOTE consider using `Arc::clone`
let rc = Rc::new(12);
//~^ NOTE this move could be avoided by cloning the original `Rc`, which is inexpensive
(rc, rc);
//~^ ERROR the type `Rc` does not implement `Copy`
//~| NOTE consider using `Rc::clone`
}
@@ -0,0 +1,49 @@
error[E0382]: use of moved value: `file`
--> $DIR/std_impls.rs:9:12
|
LL | let file = File::open("foo.txt").unwrap();
| ---- move occurs because `file` has type `File`, which does not implement the `Copy` trait
LL | (file, file);
| ---- ^^^^ value used here after move
| |
| value moved here
|
= note: you can use `File::try_clone` to duplicate a `File` instance
error[E0382]: the type `Arc` does not implement `Copy`
--> $DIR/std_impls.rs:15:11
|
LL | let arc = Arc::new(42);
| --- this move could be avoided by cloning the original `Arc`, which is inexpensive
LL |
LL | (arc, arc);
| --- ^^^ value used here after move
| |
| value moved here
|
= note: consider using `Arc::clone`
help: clone the value to increment its reference count
|
LL | (arc.clone(), arc);
| ++++++++
error[E0382]: the type `Rc` does not implement `Copy`
--> $DIR/std_impls.rs:22:10
|
LL | let rc = Rc::new(12);
| -- this move could be avoided by cloning the original `Rc`, which is inexpensive
LL |
LL | (rc, rc);
| -- ^^ value used here after move
| |
| value moved here
|
= note: consider using `Rc::clone`
help: clone the value to increment its reference count
|
LL | (rc.clone(), rc);
| ++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,8 @@
use std::borrow::Borrow;
fn foo(_v: impl IntoIterator<Item = impl Borrow<str>>) {}
fn main() {
foo(&[String::from("a")]);
//~^ ERROR the trait bound `&String: Borrow<str>` is not satisfied
}
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `&String: Borrow<str>` is not satisfied
--> $DIR/dont-suggest-borrow-whole-call-issue-155088.rs:6:5
|
LL | foo(&[String::from("a")]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Borrow<str>` is not implemented for `&String`
|
note: required by a bound in `foo`
--> $DIR/dont-suggest-borrow-whole-call-issue-155088.rs:3:42
|
LL | fn foo(_v: impl IntoIterator<Item = impl Borrow<str>>) {}
| ^^^^^^^^^^^ required by this bound in `foo`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.