Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
008ea3a
rustc_on_unimplemented: introduce format specifiers as printing optio…
mejrs May 5, 2026
fcb580c
docs: remove duplicate "hermit" entry in OS constants list
kcx1 May 18, 2026
16b12e3
tidy: alphabetize os constants list
kcx1 May 19, 2026
173bad7
fix E0371 description
42triangles May 19, 2026
7c7e9cd
loongarch: Use `intrinsics::simd` for vrepl{128}ve{0,i}
heiher May 11, 2026
20d113e
Drop skip_move_check_fns query.
cjgillot May 24, 2026
bf7a021
fix breakpoint callback registration
Walnut356 May 25, 2026
4c6f373
Merge pull request #2129 from heiher/vrepl-128-ve-0-i
Amanieu May 25, 2026
a25ec1a
move batch
zedddie May 25, 2026
480b44c
bless batch
zedddie May 25, 2026
b328c25
Update mdbook to 0.5.3
ehuss May 26, 2026
527ed7f
add optional output-dir argument
xonx4l May 26, 2026
40a7821
Remove method call generation in delegation
aerooneqq May 26, 2026
b622d86
Merge pull request #2138 from xonx4l/hexagon-gen-output-dir-arg
folkertdev May 26, 2026
d1d1302
Rollup merge of #156959 - folkertdev:stdarch-sync-2026-05-26, r=folke…
JonathanBrouwer May 26, 2026
f09612e
Rollup merge of #156541 - aerooneqq:delegation-no-method-call, r=petr…
JonathanBrouwer May 26, 2026
903a08c
Rollup merge of #156161 - mejrs:this_formatargs, r=oli-obk
JonathanBrouwer May 26, 2026
dc3bdaf
Rollup merge of #156752 - 42triangles:fix-dyn-trait-descr, r=oli-obk
JonathanBrouwer May 26, 2026
d8a003a
Rollup merge of #156761 - kcx1:fix/156730, r=tgross35
JonathanBrouwer May 26, 2026
bd59ff8
Rollup merge of #156872 - cjgillot:skip_move_check_fns, r=oli-obk
JonathanBrouwer May 26, 2026
6aa3c7e
Rollup merge of #156899 - Walnut356:lldb_batchmode, r=jieyouxu
JonathanBrouwer May 26, 2026
d9b3fef
Rollup merge of #156927 - zedddie:gsoc-batch-1-meow, r=Kivooeo
JonathanBrouwer May 26, 2026
6140aee
Rollup merge of #156947 - ehuss:update-mdbook, r=jieyouxu
JonathanBrouwer May 26, 2026
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
182 changes: 77 additions & 105 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ use smallvec::SmallVec;
use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults};
use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee};
use crate::{
AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,
ParamMode, ResolverAstLoweringExt,
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
ResolverAstLoweringExt,
};

mod generics;
Expand Down Expand Up @@ -144,24 +144,31 @@ impl<'hir> LoweringContext<'_, 'hir> {

let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method);

let body_id = self.lower_delegation_body(
let (body_id, call_expr_id) = self.lower_delegation_body(
delegation,
is_method,
param_count,
&mut generics,
span,
);

let decl =
self.lower_delegation_decl(sig_id, param_count, c_variadic, span, &generics);
let decl = self.lower_delegation_decl(
sig_id,
param_count,
c_variadic,
span,
&generics,
delegation.id,
call_expr_id,
);

let sig = self.lower_delegation_sig(sig_id, decl, span);
let ident = self.lower_ident(delegation.ident);

let generics = self.arena.alloc(hir::Generics {
has_where_clause_predicates: false,
params: self.arena.alloc_from_iter(generics.all_params(span, self)),
predicates: self.arena.alloc_from_iter(generics.all_predicates(span, self)),
params: self.arena.alloc_from_iter(generics.all_params()),
predicates: self.arena.alloc_from_iter(generics.all_predicates()),
span,
where_clause_span: span,
});
Expand Down Expand Up @@ -280,6 +287,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
c_variadic: bool,
span: Span,
generics: &GenericsGenerationResults<'hir>,
call_path_node_id: NodeId,
call_expr_id: HirId,
) -> &'hir hir::FnDecl<'hir> {
// The last parameter in C variadic functions is skipped in the signature,
// like during regular lowering.
Expand All @@ -297,7 +306,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir_id: self.next_id(),
kind: hir::TyKind::InferDelegation(hir::InferDelegation::Sig(
sig_id,
hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationGenerics {
hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationInfo {
call_expr_id,
call_path_res: self.get_resolution_id(call_path_node_id),
child_args_segment_id: generics.child.args_segment_id,
parent_args_segment_id: generics.parent.args_segment_id,
self_ty_id: generics.self_ty_id,
Expand Down Expand Up @@ -400,10 +411,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
param_count: usize,
generics: &mut GenericsGenerationResults<'hir>,
span: Span,
) -> BodyId {
) -> (BodyId, HirId) {
let block = delegation.body.as_deref();
let mut call_expr_id = HirId::INVALID;

self.lower_body(|this| {
let block_id = self.lower_body(|this| {
let mut parameters: Vec<hir::Param<'_>> = Vec::with_capacity(param_count);
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);

Expand Down Expand Up @@ -440,10 +452,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
args.push(this.lower_target_expr(&block));
}

let final_expr = this.finalize_body_lowering(delegation, args, generics, span);
let (final_expr, hir_id) =
this.finalize_body_lowering(delegation, args, generics, span);

call_expr_id = hir_id;

(this.arena.alloc_from_iter(parameters), final_expr)
})
});

debug_assert_ne!(call_expr_id, HirId::INVALID);

(block_id, call_expr_id)
}

// FIXME(fn_delegation): Alternatives for target expression lowering:
Expand All @@ -459,108 +478,59 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.mk_expr(hir::ExprKind::Block(block, None), block.span)
}

// Generates expression for the resulting body. If possible, `MethodCall` is used
// to allow autoref/autoderef for target expression. For example in:
//
// trait Trait : Sized {
// fn by_value(self) -> i32 { 1 }
// fn by_mut_ref(&mut self) -> i32 { 2 }
// fn by_ref(&self) -> i32 { 3 }
// }
//
// struct NewType(SomeType);
// impl Trait for NewType {
// reuse Trait::* { self.0 }
// }
//
// `self.0` will automatically coerce.
fn finalize_body_lowering(
&mut self,
delegation: &Delegation,
args: Vec<hir::Expr<'hir>>,
generics: &mut GenericsGenerationResults<'hir>,
span: Span,
) -> hir::Expr<'hir> {
let args = self.arena.alloc_from_iter(args);

let has_generic_args =
delegation.path.segments.iter().rev().skip(1).any(|segment| segment.args.is_some());

let call = if self
.get_resolution_id(delegation.id)
.map(|def_id| self.is_method(def_id, span))
.unwrap_or_default()
&& delegation.qself.is_none()
&& !has_generic_args
&& !args.is_empty()
{
let ast_segment = delegation.path.segments.last().unwrap();
let segment = self.lower_path_segment(
delegation.path.span,
ast_segment,
ParamMode::Optional,
GenericArgsMode::Err,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

// FIXME(fn_delegation): proper support for parent generics propagation
// in method call scenario.
let segment = self.process_segment(span, &segment, &mut generics.child);
let segment = self.arena.alloc(segment);

self.arena.alloc(hir::Expr {
hir_id: self.next_id(),
kind: hir::ExprKind::MethodCall(segment, &args[0], &args[1..], span),
span,
})
} else {
let path = self.lower_qpath(
delegation.id,
&delegation.qself,
&delegation.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

let new_path = match path {
hir::QPath::Resolved(ty, path) => {
let mut new_path = path.clone();
let len = new_path.segments.len();

new_path.segments = self.arena.alloc_from_iter(
new_path.segments.iter().enumerate().map(|(idx, segment)| {
if idx + 2 == len {
self.process_segment(span, segment, &mut generics.parent)
} else if idx + 1 == len {
self.process_segment(span, segment, &mut generics.child)
} else {
segment.clone()
}
}),
);

hir::QPath::Resolved(ty, self.arena.alloc(new_path))
}
hir::QPath::TypeRelative(ty, segment) => {
let segment = self.process_segment(span, segment, &mut generics.child);

hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
}
};
) -> (hir::Expr<'hir>, HirId) {
let path = self.lower_qpath(
delegation.id,
&delegation.qself,
&delegation.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

let new_path = match path {
hir::QPath::Resolved(ty, path) => {
let mut new_path = path.clone();
let len = new_path.segments.len();

new_path.segments = self.arena.alloc_from_iter(
new_path.segments.iter().enumerate().map(|(idx, segment)| {
if idx + 2 == len {
self.process_segment(span, segment, &mut generics.parent)
} else if idx + 1 == len {
self.process_segment(span, segment, &mut generics.child)
} else {
segment.clone()
}
}),
);

generics.self_ty_id = match new_path {
hir::QPath::Resolved(ty, _) => ty,
hir::QPath::TypeRelative(ty, _) => Some(ty),
hir::QPath::Resolved(ty, self.arena.alloc(new_path))
}
.map(|ty| ty.hir_id);
hir::QPath::TypeRelative(ty, segment) => {
let segment = self.process_segment(span, segment, &mut generics.child);

let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span))
hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
}
};

generics.self_ty_id = match new_path {
hir::QPath::Resolved(ty, _) => ty,
hir::QPath::TypeRelative(ty, _) => Some(ty),
}
.map(|ty| ty.hir_id);

let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
let args = self.arena.alloc_from_iter(args);
let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span));

let block = self.arena.alloc(hir::Block {
stmts: &[],
expr: Some(call),
Expand All @@ -570,7 +540,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
targeted_by_break: false,
});

self.mk_expr(hir::ExprKind::Block(block, None), span)
(self.mk_expr(hir::ExprKind::Block(block, None), span), call.hir_id)
}

fn process_segment(
Expand All @@ -581,8 +551,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::PathSegment<'hir> {
let details = result.generics.args_propagation_details();

// Always uplift generic params, because if they are not empty then they
// should be generated in delegation.
let generics = result.generics.into_hir_generics(self, span);
let segment = if details.should_propagate {
let generics = result.generics.into_hir_generics(self, span);
let args = generics.into_generic_args(self, span);

// Needed for better error messages (`trait-impl-wrong-args-count.rs` test).
Expand Down
45 changes: 11 additions & 34 deletions compiler/rustc_ast_lowering/src/delegation/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,22 +171,9 @@ impl<'hir> GenericsGenerationResult<'hir> {
}

impl<'hir> GenericsGenerationResults<'hir> {
pub(super) fn all_params(
&mut self,
span: Span,
ctx: &mut LoweringContext<'_, 'hir>,
) -> impl Iterator<Item = hir::GenericParam<'hir>> {
// Now we always call `into_hir_generics` both on child and parent,
// however in future we would not do that, when scenarios like
// method call will be supported (if HIR generics were not obtained
// then it means that we did not propagated them, thus we do not need
// to generate params).
let mut create_params = |result: &mut GenericsGenerationResult<'hir>| {
result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().params
};

let parent = create_params(&mut self.parent);
let child = create_params(&mut self.child);
pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
let parent = self.parent.generics.hir_generics_or_empty().params;
let child = self.child.generics.hir_generics_or_empty().params;

// Order generics, first we have parent and child lifetimes,
// then parent and child types and consts.
Expand All @@ -205,24 +192,14 @@ impl<'hir> GenericsGenerationResults<'hir> {
/// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
/// Those predicates will not affect resulting predicate inheritance and folding
/// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
pub(super) fn all_predicates(
&mut self,
span: Span,
ctx: &mut LoweringContext<'_, 'hir>,
) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
// Now we always call `into_hir_generics` both on child and parent,
// however in future we would not do that, when scenarios like
// method call will be supported (if HIR generics were not obtained
// then it means that we did not propagated them, thus we do not need
// to generate predicates).
let mut create_predicates = |result: &mut GenericsGenerationResult<'hir>| {
result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().predicates
};

let parent = create_predicates(&mut self.parent);
let child = create_predicates(&mut self.child);

parent.into_iter().chain(child).copied()
pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
self.parent
.generics
.hir_generics_or_empty()
.predicates
.into_iter()
.chain(self.child.generics.hir_generics_or_empty().predicates)
.copied()
}
}

Expand Down
Loading