Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use rustc_trait_selection::traits::{
};
use tracing::{debug, instrument};

use crate::errors;
use crate::errors::{self, ElidedLifetimesAreNotAllowedInDelegations};
use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason};

pub(crate) mod dump;
Expand Down Expand Up @@ -131,6 +131,7 @@ pub(crate) struct ItemCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
item_def_id: LocalDefId,
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
lowering_delegation_segment: bool,
}

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -241,7 +242,24 @@ fn bad_placeholder<'cx, 'tcx>(

impl<'tcx> ItemCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
ItemCtxt::new_internal(tcx, item_def_id, false)
}

fn new_internal(
tcx: TyCtxt<'tcx>,
item_def_id: LocalDefId,
delegation: bool,
) -> ItemCtxt<'tcx> {
ItemCtxt {
tcx,
item_def_id,
tainted_by_errors: Cell::new(None),
lowering_delegation_segment: delegation,
}
}

pub(crate) fn new_for_delegation(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
ItemCtxt::new_internal(tcx, item_def_id, true)
}

pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
Expand Down Expand Up @@ -335,6 +353,13 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
.emit();
ty::Region::new_error(self.tcx(), guar)
} else {
// If we found elided lifetime during lowering of delegation parent or child
// segment then emit an error, as we need a named lifetime for proper signature
// inheritance (#156848).
if self.lowering_delegation_segment {
self.tcx.dcx().emit_err(ElidedLifetimesAreNotAllowedInDelegations { span });
}

// This indicates an illegal lifetime in a non-assoc-trait position
ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq Jun 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way is unelided correct here (it should be elided)?

View changes since the review

}
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_hir_analysis/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::debug_assert_matches;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{DelegationInfo, HirId, PathSegment};
use rustc_hir::{DelegationInfo, PathSegment};
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
Expand Down Expand Up @@ -551,7 +551,7 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
}
}

let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
let (parent_args, child_args) = tcx.get_delegation_user_specified_args(def_id);
let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
let filter_self_preds = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true));
Expand Down Expand Up @@ -627,7 +627,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
}

let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
let (parent_args, child_args) = tcx.get_delegation_user_specified_args(def_id);
let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder));

Expand All @@ -640,18 +640,18 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
// they will be used during delegation signature and predicates inheritance.
// Example: reuse Trait::<'static, i32, 1>::foo::<A, B>
// we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child.
fn get_delegation_user_specified_args<'tcx>(
pub(crate) fn get_delegation_user_specified_args<'tcx>(
tcx: TyCtxt<'tcx>,
delegation_id: LocalDefId,
) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
let info = get_delegation_info(tcx, delegation_id);

let get_segment = |hir_id: HirId| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
let segment = tcx.hir_node(hir_id).expect_path_segment();
segment.res.opt_def_id().map(|def_id| (segment, def_id))
};

let ctx = ItemCtxt::new(tcx, delegation_id);
let ctx = ItemCtxt::new_for_delegation(tcx, delegation_id);
let lowerer = ctx.lowerer();

let parent_args = info.parent_args_segment_id.and_then(get_segment).map(|(segment, def_id)| {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,13 @@ pub(crate) struct DelegationSelfTypeNotSpecified {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("elided lifetimes are not allowed in delegations as we need to inherit signature")]
pub(crate) struct ElidedLifetimesAreNotAllowedInDelegations {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("method should be `async` or return a future, but it is synchronous")]
pub(crate) struct MethodShouldReturnFuture {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ pub fn provide(providers: &mut Providers) {
inferred_outlives_crate: outlives::inferred_outlives_crate,
inferred_outlives_of: outlives::inferred_outlives_of,
inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
get_delegation_user_specified_args: delegation::get_delegation_user_specified_args,
enforce_impl_non_lifetime_params_are_constrained:
impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
crate_variances: variance::crate_variances,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2065,6 +2065,10 @@ rustc_queries! {
desc { "inheriting delegation signature" }
}

query get_delegation_user_specified_args(def_id: LocalDefId) -> (&'tcx [GenericArg<'tcx>], &'tcx [GenericArg<'tcx>]) {
desc { "getting delegation user-specified args" }
}

/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
/// See `rustc_resolve::late::lifetimes` for details.
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ impl<T0, T1> Erasable for (&'_ T0, &'_ T1) {
type Storage = [u8; size_of::<(&'_ (), &'_ ())>()];
}

impl<T0, T1> Erasable for (&'_ [T0], &'_ [T1]) {
type Storage = [u8; size_of::<(&'_ [()], &'_ [()])>()];
}

macro_rules! impl_erasable_for_types_with_no_type_params {
($($ty:ty),+ $(,)?) => {
$(
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/delegation/generics/generics-gen-args-errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod test_1 {
//~| ERROR can't use generic parameters from outer item
//~| ERROR: unresolved item provided when a constant was expected
//~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
}
}

Expand All @@ -44,36 +45,45 @@ mod test_2 {

reuse foo::<> as bar1;
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<String, String> as bar2;
//~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied
//~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3;
//~^ ERROR: use of undeclared lifetime name `'asdasd`
//~| ERROR: function takes 2 lifetime arguments but 5 lifetime arguments were supplied
//~| ERROR: function takes 3 generic arguments but 2 generic arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<String, 'static, 123, asdasd> as bar4;
//~^ ERROR: cannot find type `asdasd` in this scope
//~| ERROR: function takes 2 lifetime arguments but 1 lifetime argument was supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<1, 2, _, 4, 5, _> as bar5;
//~^ ERROR: function takes 3 generic arguments but 6 generic arguments were supplied
//~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6;
//~^ ERROR: cannot find type `asd` in this scope
//~| ERROR: function takes 3 generic arguments but 5 generic arguments were supplied
//~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7;
//~^ ERROR: use of undeclared lifetime name `'a`
//~| ERROR: cannot find type `asd` in this scope
//~| ERROR: constant provided when a type was expected
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse foo::<{}, {}, {}> as bar8;
//~^ ERROR: constant provided when a type was expected
//~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
}

mod test_3 {
Expand All @@ -90,34 +100,43 @@ mod test_3 {
//~| ERROR: cannot find type `asdasa` in this scope
//~| ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: trait takes 2 generic arguments but 6 generic arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse Trait::<'static, 'static>::foo as bar2;
//~^ ERROR: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
reuse Trait::<1, 2, 3, 4, 5>::foo as bar3;
//~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse Trait::<1, 2, true>::foo as bar4;
//~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied
//~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse Trait::<'static>::foo as bar5;
//~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6;
//~^ ERROR: cannot find type `DDDD` in this scope [E0425]
//~| ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied
//~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied
//~| ERROR: method takes 2 generic arguments but 6 generic arguments were supplied
//~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature

reuse Trait::<Trait, Clone, _, 'static, dyn Send, _>::foo::<1, 2, 3, _, 6> as bar7;
//~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied
//~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied
//~| ERROR: method takes 2 generic arguments but 5 generic arguments were supplied
//~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
//~| ERROR: elided lifetimes are not allowed in delegations as we need to inherit signature
}

fn main() {}
Loading
Loading