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
// 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)
+11 -13
View File
@@ -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();
+1 -1
View File
@@ -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
+1
View File
@@ -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,
}
+1
View 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]"
+2 -2
View File
@@ -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",
+6 -17
View File
@@ -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);
+32 -8
View File
@@ -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.
+26 -32
View File
@@ -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)]
+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 \
// '//*[@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`.