mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
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:
@@ -508,7 +508,7 @@ fn finalize_body_lowering(
|
||||
|
||||
// FIXME(fn_delegation): proper support for parent generics propagation
|
||||
// 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);
|
||||
|
||||
self.arena.alloc(hir::Expr {
|
||||
@@ -534,14 +534,10 @@ fn finalize_body_lowering(
|
||||
|
||||
new_path.segments = self.arena.alloc_from_iter(
|
||||
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 {
|
||||
process_segment(&mut generics.parent, true)
|
||||
self.process_segment(span, segment, &mut generics.parent)
|
||||
} else if idx + 1 == len {
|
||||
process_segment(&mut generics.child, false)
|
||||
self.process_segment(span, segment, &mut generics.child)
|
||||
} else {
|
||||
segment.clone()
|
||||
}
|
||||
@@ -551,7 +547,7 @@ fn finalize_body_lowering(
|
||||
hir::QPath::Resolved(ty, self.arena.alloc(new_path))
|
||||
}
|
||||
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))
|
||||
}
|
||||
@@ -584,13 +580,12 @@ fn process_segment(
|
||||
span: Span,
|
||||
segment: &hir::PathSegment<'hir>,
|
||||
result: &mut GenericsGenerationResult<'hir>,
|
||||
add_lifetimes: bool,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
let details = result.generics.args_propagation_details();
|
||||
|
||||
let segment = if details.should_propagate {
|
||||
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).
|
||||
let args = if args.is_empty() { None } else { Some(args) };
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use rustc_middle::ty::GenericParamDefKind;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{Ident, Span};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
|
||||
use crate::{LoweringContext, ResolverAstLoweringExt};
|
||||
|
||||
@@ -25,22 +25,37 @@ pub(super) enum DelegationGenericsKind {
|
||||
TraitImpl(bool /* Has user-specified args */),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(super) enum GenericsPosition {
|
||||
Parent,
|
||||
Child,
|
||||
}
|
||||
|
||||
pub(super) struct DelegationGenerics<T> {
|
||||
generics: T,
|
||||
kind: DelegationGenericsKind,
|
||||
pos: GenericsPosition,
|
||||
}
|
||||
|
||||
impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> {
|
||||
fn default(generics: &'hir [ty::GenericParamDef]) -> Self {
|
||||
DelegationGenerics { generics, kind: DelegationGenericsKind::Default }
|
||||
fn default(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
|
||||
DelegationGenerics { generics, pos, kind: DelegationGenericsKind::Default }
|
||||
}
|
||||
|
||||
fn user_specified(generics: &'hir [ty::GenericParamDef]) -> Self {
|
||||
DelegationGenerics { generics, kind: DelegationGenericsKind::UserSpecified }
|
||||
fn user_specified(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
|
||||
DelegationGenerics { generics, pos, kind: DelegationGenericsKind::UserSpecified }
|
||||
}
|
||||
|
||||
fn trait_impl(generics: &'hir [ty::GenericParamDef], user_specified: bool) -> Self {
|
||||
DelegationGenerics { generics, kind: DelegationGenericsKind::TraitImpl(user_specified) }
|
||||
fn trait_impl(
|
||||
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,
|
||||
) -> &mut HirOrTyGenerics<'hir> {
|
||||
if let HirOrTyGenerics::Ty(ty) = self {
|
||||
let params = ctx.uplift_delegation_generic_params(span, ty.generics);
|
||||
*self = HirOrTyGenerics::Hir(DelegationGenerics { generics: params, kind: ty.kind });
|
||||
let rename_self = matches!(ty.pos, GenericsPosition::Child);
|
||||
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
|
||||
@@ -120,7 +141,6 @@ fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
|
||||
pub(super) fn into_generic_args(
|
||||
&self,
|
||||
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
|
||||
add_lifetimes: bool,
|
||||
span: Span,
|
||||
) -> &'hir hir::GenericArgs<'hir> {
|
||||
match self {
|
||||
@@ -128,6 +148,7 @@ pub(super) fn into_generic_args(
|
||||
bug!("Attempting to get generic args before uplifting to HIR")
|
||||
}
|
||||
HirOrTyGenerics::Hir(hir) => {
|
||||
let add_lifetimes = matches!(hir.pos, GenericsPosition::Parent);
|
||||
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 }) {
|
||||
// Considering parent generics, during signature inheritance
|
||||
// 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 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);
|
||||
|
||||
return GenericsGenerationResults {
|
||||
@@ -263,25 +289,32 @@ pub(super) fn uplift_delegation_generics(
|
||||
DelegationGenerics {
|
||||
kind: DelegationGenericsKind::SelfAndUserSpecified,
|
||||
generics: &sig_parent_params[..1],
|
||||
pos: GenericsPosition::Parent,
|
||||
}
|
||||
} else {
|
||||
DelegationGenerics::user_specified(&[])
|
||||
DelegationGenerics::user_specified(&[], GenericsPosition::Parent)
|
||||
}
|
||||
} else {
|
||||
let skip_self = usize::from(!generate_self);
|
||||
DelegationGenerics::default(&sig_parent_params[skip_self..])
|
||||
DelegationGenerics::default(
|
||||
&sig_parent_params[skip_self..],
|
||||
GenericsPosition::Parent,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
DelegationGenerics::default(&[])
|
||||
DelegationGenerics::default(&[], GenericsPosition::Parent)
|
||||
};
|
||||
|
||||
let child_generics = if child_user_specified {
|
||||
let synth_params_index =
|
||||
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 {
|
||||
DelegationGenerics::default(sig_params)
|
||||
DelegationGenerics::default(sig_params, GenericsPosition::Child)
|
||||
};
|
||||
|
||||
GenericsGenerationResults {
|
||||
@@ -296,6 +329,7 @@ fn uplift_delegation_generic_params(
|
||||
&mut self,
|
||||
span: Span,
|
||||
params: &'hir [ty::GenericParamDef],
|
||||
rename_self: bool,
|
||||
) -> &'hir hir::Generics<'hir> {
|
||||
let params = self.arena.alloc_from_iter(params.iter().map(|p| {
|
||||
let def_kind = match p.kind {
|
||||
@@ -304,7 +338,20 @@ fn uplift_delegation_generic_params(
|
||||
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 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,
|
||||
}
|
||||
}
|
||||
Architecture::Sparc32Plus => elf::EF_SPARC_32PLUS,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
use hir::def::DefKind;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_hir::def_id::LocalDefIdMap;
|
||||
use rustc_hir::definitions::{
|
||||
DefPathData, PerParentDisambiguatorState, PerParentDisambiguatorsMap,
|
||||
};
|
||||
use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir::interpret::{
|
||||
@@ -108,7 +105,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
|
||||
ecx: &mut InterpCx<'tcx, M>,
|
||||
alloc_id: AllocId,
|
||||
mutability: Mutability,
|
||||
disambiguators: Option<&mut LocalDefIdMap<PerParentDisambiguatorState>>,
|
||||
disambiguator: Option<&mut PerParentDisambiguatorState>,
|
||||
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, InternError> {
|
||||
trace!("intern_shallow {:?}", alloc_id);
|
||||
// remove allocation
|
||||
@@ -132,7 +129,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
|
||||
static_id,
|
||||
alloc_id,
|
||||
alloc,
|
||||
disambiguators.expect("disambiguators needed"),
|
||||
disambiguator.expect("disambiguator needed"),
|
||||
);
|
||||
} else {
|
||||
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||
@@ -147,19 +144,18 @@ fn intern_as_new_static<'tcx>(
|
||||
static_id: LocalDefId,
|
||||
alloc_id: AllocId,
|
||||
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
|
||||
// `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.
|
||||
let feed = tcx.create_def(
|
||||
static_id,
|
||||
None,
|
||||
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
|
||||
Some(DefPathData::NestedStatic),
|
||||
//FIXME(oli-obk): cleanup (https://github.com/rust-lang/rust/pull/155547#discussion_r3110792640)
|
||||
disambiguators.get_or_create(static_id),
|
||||
disambiguator,
|
||||
);
|
||||
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,
|
||||
ret: &MPlaceTy<'tcx>,
|
||||
) -> 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
|
||||
// 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
|
||||
// recursively in the loop below.
|
||||
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`.
|
||||
// But still change its mutability to match the requested one.
|
||||
let (kind, alloc) = ecx.memory.alloc_map.get_mut(&base_alloc_id).unwrap();
|
||||
prepare_alloc(*ecx.tcx, *kind, alloc, base_mutability)?;
|
||||
alloc.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
|
||||
} 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`",
|
||||
// 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
|
||||
// `static mut`.
|
||||
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);
|
||||
}
|
||||
if found_bad_mutable_ptr {
|
||||
|
||||
@@ -50,11 +50,6 @@ pub enum 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 {
|
||||
use PrintKind::*;
|
||||
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 {
|
||||
Target {
|
||||
@@ -24,6 +26,7 @@ pub(crate) fn target() -> Target {
|
||||
// linker error, so set it to `true` here.
|
||||
// FIXME(#146996): Remove this override once #146996 has been fixed.
|
||||
default_uwtable: false,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS,
|
||||
..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
|
||||
// thumb-mode. See the thumbv7neon variant for enabling both.
|
||||
@@ -23,6 +25,7 @@ pub(crate) fn target() -> Target {
|
||||
max_atomic_width: Some(64),
|
||||
mcount: "\u{1}__gnu_mcount_nc".into(),
|
||||
llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
|
||||
supported_sanitizers: SanitizerSet::ADDRESS,
|
||||
..base::linux_gnu::opts()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
|
||||
llvm_target: "thumbv7a-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-A".into()),
|
||||
tier: Some(2),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
|
||||
llvm_target: "thumbv7a-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
|
||||
llvm_target: "thumbv7r-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-R".into()),
|
||||
tier: Some(2),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
|
||||
llvm_target: "thumbv7r-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
|
||||
llvm_target: "thumbv8r-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
//! those target flags doesn't automatically rebuild libcore / liballoc with
|
||||
//! 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
|
||||
//! 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};
|
||||
|
||||
|
||||
@@ -363,6 +363,7 @@ pub(super) fn maybe_report_ambiguity(
|
||||
if impl_candidates.len() < 40 {
|
||||
self.report_similar_impl_candidates(
|
||||
impl_candidates.as_slice(),
|
||||
obligation,
|
||||
trait_pred,
|
||||
obligation.cause.body_id,
|
||||
&mut err,
|
||||
|
||||
@@ -1973,6 +1973,7 @@ pub(super) fn find_similar_impl_candidates(
|
||||
pub(super) fn report_similar_impl_candidates(
|
||||
&self,
|
||||
impl_candidates: &[ImplCandidate<'tcx>],
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
body_def_id: LocalDefId,
|
||||
err: &mut Diag<'_>,
|
||||
@@ -2037,6 +2038,20 @@ pub(super) fn report_similar_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
|
||||
// that failed. This should uncover a better hint for what *is* implemented.
|
||||
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);
|
||||
self.report_similar_impl_candidates(
|
||||
&impl_candidates,
|
||||
obligation,
|
||||
trait_pred,
|
||||
body_def_id,
|
||||
err,
|
||||
@@ -3137,6 +3153,7 @@ fn try_to_add_help_message(
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
|
||||
if !self.report_similar_impl_candidates(
|
||||
&impl_candidates,
|
||||
obligation,
|
||||
trait_predicate,
|
||||
body_def_id,
|
||||
err,
|
||||
|
||||
@@ -1584,6 +1584,39 @@ pub fn extract_callable_info(
|
||||
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(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
@@ -1857,6 +1890,15 @@ pub(super) fn suggest_add_reference_to_arg(
|
||||
if let hir::ExprKind::AddrOf(_, _, _) = expr.kind {
|
||||
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_pre = match self.tcx.parent_hir_node(expr.hir_id) {
|
||||
Node::Expr(e)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::definitions::{
|
||||
DefPathData, PerParentDisambiguatorState, PerParentDisambiguatorsMap,
|
||||
};
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{self as hir, ConstItemRhs, ImplItemImplKind, ItemKind};
|
||||
use rustc_middle::query::Providers;
|
||||
@@ -131,7 +129,7 @@ struct RPITVisitor<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
synthetics: Vec<LocalDefId>,
|
||||
data: DefPathData,
|
||||
disambiguators: &'a mut LocalDefIdMap<PerParentDisambiguatorState>,
|
||||
disambiguator: &'a mut PerParentDisambiguatorState,
|
||||
}
|
||||
|
||||
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,
|
||||
opaque.def_id,
|
||||
self.data,
|
||||
&mut self.disambiguators,
|
||||
&mut self.disambiguator,
|
||||
));
|
||||
intravisit::walk_opaque_ty(self, opaque)
|
||||
}
|
||||
@@ -151,7 +149,7 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
|
||||
def_id: LocalDefId,
|
||||
) -> DefIdMap<Vec<DefId>> {
|
||||
let item = tcx.hir_expect_item(def_id);
|
||||
let disambiguators = &mut Default::default();
|
||||
let disambiguator = &mut PerParentDisambiguatorState::new(def_id);
|
||||
match item.kind {
|
||||
ItemKind::Trait(.., trait_item_refs) => trait_item_refs
|
||||
.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 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);
|
||||
let defs = visitor
|
||||
.synthetics
|
||||
@@ -199,7 +197,7 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
|
||||
return Some((did, vec![]));
|
||||
};
|
||||
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()
|
||||
});
|
||||
Some((did, iter.collect()))
|
||||
@@ -223,7 +221,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_ty_def_id: LocalDefId,
|
||||
data: DefPathData,
|
||||
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>,
|
||||
disambiguator: &mut PerParentDisambiguatorState,
|
||||
) -> LocalDefId {
|
||||
let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
|
||||
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) =
|
||||
@@ -242,7 +240,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
None,
|
||||
DefKind::AssocTy,
|
||||
Some(data),
|
||||
disambiguators.get_or_create(trait_def_id),
|
||||
disambiguator,
|
||||
);
|
||||
|
||||
let local_def_id = trait_assoc_ty.def_id();
|
||||
@@ -285,7 +283,7 @@ fn associated_type_for_impl_trait_in_impl(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_assoc_def_id: DefId,
|
||||
impl_fn: &hir::ImplItem<'_>,
|
||||
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>,
|
||||
disambiguator: &mut PerParentDisambiguatorState,
|
||||
) -> LocalDefId {
|
||||
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,
|
||||
DefKind::AssocTy,
|
||||
Some(data),
|
||||
disambiguators.get_or_create(impl_local_def_id),
|
||||
disambiguator,
|
||||
);
|
||||
|
||||
let local_def_id = impl_assoc_ty.def_id();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
|
||||
//! 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.
|
||||
//!
|
||||
//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
/// [`read`]: File::read
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[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 {
|
||||
inner: fs_imp::File,
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(deprecated_suggestion)]
|
||||
#![feature(diagnostic_on_move)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_masked)]
|
||||
#![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]"
|
||||
@@ -516,7 +516,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> {
|
||||
Managarm => "Managarm",
|
||||
Motor => "Motor OS",
|
||||
NetBsd => "NetBSD",
|
||||
None => "bare-metal", // FIXME(scrabsha): is this appropriate?
|
||||
None => "bare-metal",
|
||||
Nto => "QNX Neutrino",
|
||||
NuttX => "NuttX",
|
||||
OpenBsd => "OpenBSD",
|
||||
@@ -593,7 +593,7 @@ fn human_readable_target_env(env: Symbol) -> Option<&'static str> {
|
||||
// tidy-alphabetical-start
|
||||
Gnu => "GNU",
|
||||
MacAbi => "Catalyst",
|
||||
Mlibc => "mac ABI",
|
||||
Mlibc => "Managarm C Library",
|
||||
Msvc => "MSVC",
|
||||
Musl => "musl",
|
||||
Newlib => "Newlib",
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
use crate::fold::DocFolder;
|
||||
use crate::formats::Impl;
|
||||
use crate::formats::item_type::ItemType;
|
||||
use crate::html::markdown::short_markdown_summary;
|
||||
use crate::html::render::IndexItem;
|
||||
use crate::html::render::search_index::get_function_type_for_search;
|
||||
use crate::html::render::{IndexItem, IndexItemInfo};
|
||||
use crate::visit_lib::RustdocEffectiveVisibilities;
|
||||
|
||||
/// 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());
|
||||
|
||||
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
|
||||
// For searching purposes, a re-export is a duplicate if:
|
||||
//
|
||||
// - 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,
|
||||
};
|
||||
let (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id();
|
||||
let search_type = get_function_type_for_search(
|
||||
item,
|
||||
let info = IndexItemInfo::new(
|
||||
tcx,
|
||||
clean_impl_generics(cache.parent_stack.last()).as_ref(),
|
||||
parent_did,
|
||||
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 {
|
||||
ty: item.type_(),
|
||||
defid: Some(defid),
|
||||
name,
|
||||
module_path: parent_path.to_vec(),
|
||||
desc,
|
||||
parent: parent_did,
|
||||
parent_idx: None,
|
||||
trait_parent,
|
||||
trait_parent_idx: None,
|
||||
exact_module_path: None,
|
||||
impl_id,
|
||||
search_type,
|
||||
aliases,
|
||||
is_deprecated,
|
||||
is_unstable,
|
||||
info,
|
||||
};
|
||||
|
||||
cache.search_index.push(index_item);
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
pub(crate) use self::context::*;
|
||||
pub(crate) use self::span_map::{LinkFromSrc, collect_spans_and_sources};
|
||||
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::error::Error;
|
||||
use crate::formats::Impl;
|
||||
@@ -79,8 +79,9 @@
|
||||
print_type, print_where_clause, visibility_print_with_space,
|
||||
};
|
||||
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::{highlight, sources};
|
||||
use crate::scrape_examples::{CallData, CallLocation};
|
||||
@@ -124,25 +125,48 @@ enum RenderMode {
|
||||
// Helper structs for rendering items/sidebars and carrying along contextual
|
||||
// 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
|
||||
/// by hand to a large JS file at the end of cache-creation.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct IndexItem {
|
||||
pub(crate) ty: ItemType,
|
||||
pub(crate) defid: Option<DefId>,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) module_path: Vec<Symbol>,
|
||||
pub(crate) desc: String,
|
||||
pub(crate) parent: Option<DefId>,
|
||||
pub(crate) parent_idx: Option<usize>,
|
||||
pub(crate) trait_parent: Option<DefId>,
|
||||
pub(crate) trait_parent_idx: Option<usize>,
|
||||
pub(crate) exact_module_path: Option<Vec<Symbol>>,
|
||||
pub(crate) impl_id: Option<DefId>,
|
||||
pub(crate) search_type: Option<IndexItemFunctionType>,
|
||||
pub(crate) aliases: Box<[Symbol]>,
|
||||
pub(crate) is_deprecated: bool,
|
||||
pub(crate) is_unstable: bool,
|
||||
pub(crate) info: IndexItemInfo,
|
||||
}
|
||||
|
||||
/// A type used for the search index.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use rustc_ast::join_path_syms;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
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_middle::ty::TyCtxt;
|
||||
use rustc_span::def_id::DefId;
|
||||
@@ -29,7 +29,9 @@
|
||||
use crate::formats::cache::{Cache, OrphanImplItem};
|
||||
use crate::formats::item_type::ItemType;
|
||||
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)]
|
||||
pub(crate) struct SerializedSearchIndex {
|
||||
@@ -1270,29 +1272,18 @@ pub(crate) fn build_index(
|
||||
&cache.orphan_impl_items
|
||||
{
|
||||
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 {
|
||||
ty: item.type_(),
|
||||
defid: item.item_id.as_def_id(),
|
||||
name: item.name.unwrap(),
|
||||
module_path: fqp[..fqp.len() - 1].to_vec(),
|
||||
desc,
|
||||
parent: Some(parent),
|
||||
parent_idx: None,
|
||||
trait_parent,
|
||||
trait_parent_idx: None,
|
||||
exact_module_path: None,
|
||||
impl_id,
|
||||
search_type: get_function_type_for_search(
|
||||
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(),
|
||||
info,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1301,11 +1292,10 @@ pub(crate) fn build_index(
|
||||
search_index.sort_unstable_by(|k1, k2| {
|
||||
// `sort_unstable_by_key` produces lifetime errors
|
||||
// HACK(rustdoc): should not be sorting `CrateNum` or `DefIndex`, this will soon go away, too
|
||||
let k1 =
|
||||
(&k1.module_path, k1.name.as_str(), &k1.ty, k1.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(&k1, &k2)
|
||||
fn key(i: &IndexItem) -> (&[Symbol], &str, ItemType, Option<(DefIndex, CrateNum)>) {
|
||||
(&i.module_path, i.name.as_str(), i.info.ty, i.parent.map(|id| (id.index, id.krate)))
|
||||
}
|
||||
Ord::cmp(&key(k1), &key(k2))
|
||||
});
|
||||
|
||||
// Now, convert to an on-disk search index format
|
||||
@@ -1466,7 +1456,7 @@ pub(crate) fn build_index(
|
||||
if fqp.last() != Some(&item.name) {
|
||||
return None;
|
||||
}
|
||||
let path = if item.ty == ItemType::Macro
|
||||
let path = if item.info.ty == ItemType::Macro
|
||||
&& find_attr!(tcx, defid, MacroExport { .. })
|
||||
{
|
||||
// `#[macro_export]` always exports to the crate root.
|
||||
@@ -1501,8 +1491,9 @@ pub(crate) fn build_index(
|
||||
if item.impl_id.is_some()
|
||||
&& let Some(parent_idx) = item.parent_idx
|
||||
{
|
||||
let count =
|
||||
associated_item_duplicates.entry((parent_idx, item.ty, item.name)).or_insert(0);
|
||||
let count = associated_item_duplicates
|
||||
.entry((parent_idx, item.info.ty, item.name))
|
||||
.or_insert(0);
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
@@ -1525,24 +1516,27 @@ pub(crate) fn build_index(
|
||||
let new_entry_id = serialized_index.add_entry(
|
||||
item.name,
|
||||
EntryData {
|
||||
ty: item.ty,
|
||||
ty: item.info.ty,
|
||||
parent: item.parent_idx,
|
||||
trait_parent: item.trait_parent_idx,
|
||||
module_path,
|
||||
exact_module_path,
|
||||
deprecated: item.is_deprecated,
|
||||
unstable: item.is_unstable,
|
||||
deprecated: item
|
||||
.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) =
|
||||
item.impl_id
|
||||
&& let Some(parent_idx) = item.parent_idx
|
||||
&& associated_item_duplicates
|
||||
.get(&(parent_idx, item.ty, item.name))
|
||||
.get(&(parent_idx, item.info.ty, item.name))
|
||||
.copied()
|
||||
.unwrap_or(0)
|
||||
> 1
|
||||
{
|
||||
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 cnum = tcx.extern_mod_stmt_cnum(local_def_id).unwrap_or(LOCAL_CRATE)
|
||||
&& let Some(ExternalLocation::Remote { url, is_absolute }) =
|
||||
@@ -1555,12 +1549,12 @@ pub(crate) fn build_index(
|
||||
},
|
||||
krate: crate_idx,
|
||||
},
|
||||
item.desc.to_string(),
|
||||
item.info.desc.to_string(),
|
||||
);
|
||||
|
||||
// Aliases
|
||||
// -------
|
||||
for alias in &item.aliases[..] {
|
||||
for alias in &item.info.aliases {
|
||||
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_output = BTreeSet::new();
|
||||
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,
|
||||
// because the postings list has to fill in an empty array for each
|
||||
// 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());
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -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() { }
|
||||
@@ -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() {}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
//@ has all_targets/fn.foo.html \
|
||||
// '//*[@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 \
|
||||
// OpenHarmony or relibc or SGX or Simulator or WASIp1 or WASIp2 or WASIp3 or \
|
||||
// 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
|
||||
// mod test_4 {
|
||||
// trait Trait<'a, A, const B: bool> {
|
||||
// fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
|
||||
// f()
|
||||
// }
|
||||
// }
|
||||
// Test recursive delegation through trait
|
||||
mod test_4 {
|
||||
trait Trait<'a, A, const B: bool> {
|
||||
fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
// struct X;
|
||||
// impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
|
||||
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 Trait::foo;
|
||||
reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
|
||||
|
||||
// trait Trait2 {
|
||||
// reuse foo;
|
||||
// reuse bar;
|
||||
// }
|
||||
trait Trait2 {
|
||||
reuse foo;
|
||||
reuse bar;
|
||||
}
|
||||
|
||||
// reuse Trait2::foo as foo2;
|
||||
// reuse Trait2::foo::<'static, X, (), true, false, (), ()> as foo3;
|
||||
// reuse Trait2::bar as bar2;
|
||||
// reuse Trait2::bar::<X> as bar3;
|
||||
impl Trait2 for () {}
|
||||
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
reuse <() as Trait2>::foo as foo2;
|
||||
reuse <() as Trait2>::foo::<'static, X, (), true, false, (), ()> as foo3;
|
||||
reuse <() as Trait2>::bar as bar2;
|
||||
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() {
|
||||
test_1::check();
|
||||
test_2::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`.
|
||||
Reference in New Issue
Block a user