Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d715ef4
debuginfo: slices are DW_TAG_array_type's
shua Feb 26, 2026
f398585
adding debuginfo tests for str repr llvm di
shua May 5, 2026
45adab8
Pass user-provided llvm_args after target spec llvm_args.
guybedford May 13, 2026
6bd5ab9
Emit error when self type is not specified and accessed
aerooneqq May 14, 2026
282ec28
Implement pinned drop sugar
P8L1 May 14, 2026
1b7609c
Disable `main_needs_argc_argv` for Wasm
daxpedda May 14, 2026
9faff71
actually run the temp_dir doctest
RalfJung May 12, 2026
5a12d48
Prefer tracing::instrument.
cjgillot May 14, 2026
d76d4cd
Untuple method parameters.
cjgillot May 14, 2026
6e7b089
Use DropCtxt::new_block and new_block_with_statements systematically.
cjgillot May 14, 2026
85dfeda
Correctly handle associated items in rustdoc macro expansion
GuillaumeGomez May 14, 2026
899be9f
Add regression tests for associated items in rustdoc macro expansion
GuillaumeGomez May 14, 2026
8909e79
Require UTF-8 in `Utf8Pattern::StringPattern`
qaijuang May 13, 2026
d24fd77
Make const param default test reproduce original ICE
cijiugechu May 15, 2026
5d15124
coverage: Reduce and clarify the context-mismatch test case
Zalathar May 15, 2026
860813d
Require EIIs to be defined when we compile a rust dylib
bjorn3 May 8, 2026
ae95a55
Rollup merge of #153238 - shua:lldb-rcstr, r=davidtwco
JonathanBrouwer May 15, 2026
a8591b8
Rollup merge of #156319 - bjorn3:eii_dylib_require_def, r=jdonszelmann
JonathanBrouwer May 15, 2026
4903ba3
Rollup merge of #156452 - P8L1:implement-pin-drop-sugar-upstream, r=p…
JonathanBrouwer May 15, 2026
d89065f
Rollup merge of #156554 - guybedford:wasm-use-legacy-eh, r=alexcrichton
JonathanBrouwer May 15, 2026
b45cdbb
Rollup merge of #156571 - daxpedda:wasm-main, r=alexcrichton
JonathanBrouwer May 15, 2026
f6ab74f
Rollup merge of #156600 - cijiugechu:false-negative-test, r=BoxyUwU
JonathanBrouwer May 15, 2026
ee7b2c7
Rollup merge of #156493 - RalfJung:run-temp-dir, r=ChrisDenton
JonathanBrouwer May 15, 2026
e8ddb3a
Rollup merge of #156556 - qaijuang:issue-156491-str-replace-utf8-patt…
JonathanBrouwer May 15, 2026
44bd8a0
Rollup merge of #156565 - aerooneqq:delegation-self-type-ice, r=petro…
JonathanBrouwer May 15, 2026
574d2b0
Rollup merge of #156586 - cjgillot:elaborate-new-block, r=oli-obk
JonathanBrouwer May 15, 2026
9c021d1
Rollup merge of #156587 - GuillaumeGomez:assoc-items-macro-expansion,…
JonathanBrouwer May 15, 2026
32c54c2
Rollup merge of #156604 - Zalathar:context-mismatch, r=mu001999
JonathanBrouwer May 15, 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
13 changes: 13 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3867,6 +3867,19 @@ pub struct Fn {
pub eii_impls: ThinVec<EiiImpl>,
}

impl Fn {
pub fn is_pin_drop_sugar(&self) -> bool {
self.ident.name == sym::drop
&& self
.sig
.decl
.inputs
.first()
.and_then(|param| param.to_self())
.is_some_and(|eself| matches!(eself.node, SelfKind::Pinned(None, Mutability::Mut)))
}
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct EiiImpl {
pub node_id: NodeId,
Expand Down
73 changes: 56 additions & 17 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,52 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}

fn resolve_pin_drop_sugar_impl_item(
&self,
i: &AssocItem,
ident: Ident,
span: Span,
) -> (Ident, Result<DefId, ErrorGuaranteed>) {
let trait_item_def_id = self
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented")
});

let is_pin_drop_sugar = match &i.kind {
AssocItemKind::Fn(fn_kind) => fn_kind.is_pin_drop_sugar(),
_ => false,
};
let def_id = match trait_item_def_id {
Ok(def_id) => def_id,
Err(guar) => return (ident, Err(guar)),
};
if !is_pin_drop_sugar {
return (ident, Ok(def_id));
}

let is_drop_pin_drop = self
.tcx
.lang_items()
.drop_trait()
.is_some_and(|drop_trait| self.tcx.parent(def_id) == drop_trait);
if is_drop_pin_drop {
// Associated item collection still derives the impl item's name from HIR.
return (Ident::new(sym::pin_drop, ident.span), Ok(def_id));
}

let guar = self
.dcx()
.struct_span_err(
i.span,
"method `drop` with `&pin mut self` is only supported for the `Drop` trait",
)
.with_span_label(i.span, "not a `Drop::pin_drop` implementation")
.emit();
(ident, Err(guar))
}

fn lower_impl_item(
&mut self,
i: &AssocItem,
Expand Down Expand Up @@ -1309,26 +1355,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
};

let span = self.lower_span(i.span);
let (effective_ident, impl_kind) = if is_in_trait_impl {
let (effective_ident, trait_item_def_id) =
self.resolve_pin_drop_sugar_impl_item(i, ident, span);
(effective_ident, ImplItemImplKind::Trait { defaultness, trait_item_def_id })
} else {
(ident, ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) })
};

let item = hir::ImplItem {
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
ident: self.lower_ident(effective_ident),
generics,
impl_kind: if is_in_trait_impl {
ImplItemImplKind::Trait {
defaultness,
trait_item_def_id: self
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
self.dcx().span_delayed_bug(
span,
"could not resolve trait item being implemented",
)
}),
}
} else {
ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
},
impl_kind,
kind,
span,
has_delayed_lints: !self.delayed_lints.is_empty(),
Expand Down
49 changes: 30 additions & 19 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,20 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
);

let pointee_type_di_node = type_di_node(cx, pointee_type);
let pointee_type_di_node = match pointee_type.kind() {
// `&[T]` will look like `{ data_ptr: *const T, length: usize }`
ty::Slice(element_type) => type_di_node(cx, *element_type),
// `&str` will look like `{ data_ptr: *const u8, length: usize }`
ty::Str => type_di_node(cx, cx.tcx.types.u8),

// `&dyn K` will look like `{ pointer: _, vtable: _}`
// any Adt `Foo` containing an unsized type (eg `&[_]` or `&dyn _`)
// will look like `{ data_ptr: *const Foo, length: usize }`
// and thin pointers `&Foo` will just look like `*const Foo`.
//
// in all those cases, we just use the pointee_type
_ => type_di_node(cx, pointee_type),
};

return_if_di_node_created_in_meantime!(cx, unique_type_id);

Expand Down Expand Up @@ -389,26 +402,11 @@ fn build_dyn_type_di_node<'ll, 'tcx>(
}

/// Create debuginfo for `[T]` and `str`. These are unsized.
///
/// NOTE: We currently emit just emit the debuginfo for the element type here
/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
/// `*const T` for the `data_ptr` field of the corresponding wide-pointer
/// debuginfo of `&[T]`.
///
/// It would be preferable and more accurate if we emitted a DIArray of T
/// without an upper bound instead. That is, LLVM already supports emitting
/// debuginfo of arrays of unknown size. But GDB currently seems to end up
/// in an infinite loop when confronted with such a type.
///
/// As a side effect of the current encoding every instance of a type like
/// `struct Foo { unsized_field: [u8] }` will look like
/// `struct Foo { unsized_field: u8 }` in debuginfo. If the length of the
/// slice is zero, then accessing `unsized_field` in the debugger would
/// result in an out-of-bounds access.
fn build_slice_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
slice_type: Ty<'tcx>,
unique_type_id: UniqueTypeId<'tcx>,
span: Span,
) -> DINodeCreationResult<'ll> {
let element_type = match slice_type.kind() {
ty::Slice(element_type) => *element_type,
Expand All @@ -423,7 +421,20 @@ fn build_slice_type_di_node<'ll, 'tcx>(

let element_type_di_node = type_di_node(cx, element_type);
return_if_di_node_created_in_meantime!(cx, unique_type_id);
DINodeCreationResult { di_node: element_type_di_node, already_stored_in_typemap: false }
let (size, align) = cx.spanned_size_and_align_of(slice_type, span);
let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, -1) };
let subscripts = &[subrange];
let di_node = unsafe {
llvm::LLVMDIBuilderCreateArrayType(
DIB(cx),
size.bits(),
align.bits() as u32,
element_type_di_node,
subscripts.as_ptr(),
subscripts.len() as c_uint,
)
};
DINodeCreationResult { di_node, already_stored_in_typemap: false }
}

/// Get the debuginfo node for the given type.
Expand Down Expand Up @@ -454,7 +465,7 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
}
ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span),
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id, span),
ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ unsafe fn configure_llvm(sess: &Session) {

let cg_opts = sess.opts.cg.llvm_args.iter().map(AsRef::as_ref);
let tg_opts = sess.target.llvm_args.iter().map(AsRef::as_ref);
let sess_args = cg_opts.chain(tg_opts);
// Target-spec args are passed to LLVM before user `-Cllvm-args`. LLVM's
// `cl::opt` parser is last-wins, so this lets `-Cllvm-args=...` override
// a value already set in the target spec (e.g. `-wasm-use-legacy-eh`).
let sess_args = tg_opts.chain(cg_opts);

let user_specified_args: FxHashSet<_> =
sess_args.clone().map(|s| llvm_arg_to_arg_name(s)).filter(|s| !s.is_empty()).collect();
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_middle::ty::{
use rustc_span::{ErrorGuaranteed, Span, kw};

use crate::collect::ItemCtxt;
use crate::errors::DelegationSelfTypeNotSpecified;
use crate::hir_ty_lowering::HirTyLowerer;

type RemapTable = FxHashMap<u32, u32>;
Expand Down Expand Up @@ -284,6 +285,12 @@ fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) ->
ctx.lower_ty(tcx.hir_node(id).expect_ty())
})
.unwrap_or_else(|| {
// It is possible to attempt to get self type when it is used in signature
// (i.e., `fn default() -> Self`), so emit error here in addition to possible
// `mismatched types` error (see #156388).
let err = DelegationSelfTypeNotSpecified { span: tcx.def_span(delegation_id) };
tcx.dcx().emit_err(err);

Ty::new_error_with_message(
tcx,
tcx.def_span(delegation_id),
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,14 @@ pub(crate) struct UnsupportedDelegation<'a> {
pub callee_span: Span,
}

#[derive(Diagnostic)]
#[diag("delegation self type is not specified")]
#[help("consider explicitly specifying self type: `reuse </* Type */ as Trait>::function`")]
pub(crate) struct DelegationSelfTypeNotSpecified {
#[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
Loading
Loading