Skip to content

Commit 07d4408

Browse files
committed
Auto merge of #156610 - Zalathar:rollup-uLJGkLm, r=Zalathar
Rollup of 11 pull requests Successful merges: - #148788 (Unconstrained parameter fix) - #153238 (debuginfo: slices are DW_TAG_array_type's) - #155521 (Add lint againts invalid runtime symbol definitions) - #156319 (Require EIIs to be defined when we compile a rust dylib) - #156452 (Implement pinned drop sugar) - #156600 (Make const param default test reproduce original ICE) - #156493 (actually run the temp_dir doctest) - #156556 (Require UTF-8 in `Utf8Pattern::StringPattern`) - #156565 (delegation: emit error when self type is not specified and accessed) - #156586 (Use DropCtxt::new_block and new_block_with_statements systematically.) - #156587 (Correctly handle associated items in rustdoc macro expansion)
2 parents 88ba7fb + 52569ac commit 07d4408

103 files changed

Lines changed: 2442 additions & 415 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4267,6 +4267,7 @@ dependencies = [
42674267
"rustc_parse_format",
42684268
"rustc_session",
42694269
"rustc_span",
4270+
"rustc_symbol_mangling",
42704271
"rustc_target",
42714272
"rustc_trait_selection",
42724273
"smallvec",

compiler/rustc_ast/src/ast.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3867,6 +3867,19 @@ pub struct Fn {
38673867
pub eii_impls: ThinVec<EiiImpl>,
38683868
}
38693869

3870+
impl Fn {
3871+
pub fn is_pin_drop_sugar(&self) -> bool {
3872+
self.ident.name == sym::drop
3873+
&& self
3874+
.sig
3875+
.decl
3876+
.inputs
3877+
.first()
3878+
.and_then(|param| param.to_self())
3879+
.is_some_and(|eself| matches!(eself.node, SelfKind::Pinned(None, Mutability::Mut)))
3880+
}
3881+
}
3882+
38703883
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
38713884
pub struct EiiImpl {
38723885
pub node_id: NodeId,

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,52 @@ impl<'hir> LoweringContext<'_, 'hir> {
11921192
})
11931193
}
11941194

1195+
fn resolve_pin_drop_sugar_impl_item(
1196+
&self,
1197+
i: &AssocItem,
1198+
ident: Ident,
1199+
span: Span,
1200+
) -> (Ident, Result<DefId, ErrorGuaranteed>) {
1201+
let trait_item_def_id = self
1202+
.get_partial_res(i.id)
1203+
.and_then(|r| r.expect_full_res().opt_def_id())
1204+
.ok_or_else(|| {
1205+
self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented")
1206+
});
1207+
1208+
let is_pin_drop_sugar = match &i.kind {
1209+
AssocItemKind::Fn(fn_kind) => fn_kind.is_pin_drop_sugar(),
1210+
_ => false,
1211+
};
1212+
let def_id = match trait_item_def_id {
1213+
Ok(def_id) => def_id,
1214+
Err(guar) => return (ident, Err(guar)),
1215+
};
1216+
if !is_pin_drop_sugar {
1217+
return (ident, Ok(def_id));
1218+
}
1219+
1220+
let is_drop_pin_drop = self
1221+
.tcx
1222+
.lang_items()
1223+
.drop_trait()
1224+
.is_some_and(|drop_trait| self.tcx.parent(def_id) == drop_trait);
1225+
if is_drop_pin_drop {
1226+
// Associated item collection still derives the impl item's name from HIR.
1227+
return (Ident::new(sym::pin_drop, ident.span), Ok(def_id));
1228+
}
1229+
1230+
let guar = self
1231+
.dcx()
1232+
.struct_span_err(
1233+
i.span,
1234+
"method `drop` with `&pin mut self` is only supported for the `Drop` trait",
1235+
)
1236+
.with_span_label(i.span, "not a `Drop::pin_drop` implementation")
1237+
.emit();
1238+
(ident, Err(guar))
1239+
}
1240+
11951241
fn lower_impl_item(
11961242
&mut self,
11971243
i: &AssocItem,
@@ -1309,26 +1355,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
13091355
};
13101356

13111357
let span = self.lower_span(i.span);
1358+
let (effective_ident, impl_kind) = if is_in_trait_impl {
1359+
let (effective_ident, trait_item_def_id) =
1360+
self.resolve_pin_drop_sugar_impl_item(i, ident, span);
1361+
(effective_ident, ImplItemImplKind::Trait { defaultness, trait_item_def_id })
1362+
} else {
1363+
(ident, ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) })
1364+
};
1365+
13121366
let item = hir::ImplItem {
13131367
owner_id: hir_id.expect_owner(),
1314-
ident: self.lower_ident(ident),
1368+
ident: self.lower_ident(effective_ident),
13151369
generics,
1316-
impl_kind: if is_in_trait_impl {
1317-
ImplItemImplKind::Trait {
1318-
defaultness,
1319-
trait_item_def_id: self
1320-
.get_partial_res(i.id)
1321-
.and_then(|r| r.expect_full_res().opt_def_id())
1322-
.ok_or_else(|| {
1323-
self.dcx().span_delayed_bug(
1324-
span,
1325-
"could not resolve trait item being implemented",
1326-
)
1327-
}),
1328-
}
1329-
} else {
1330-
ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
1331-
},
1370+
impl_kind,
13321371
kind,
13331372
span,
13341373
has_delayed_lints: !self.delayed_lints.is_empty(),

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,20 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
152152
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
153153
);
154154

155-
let pointee_type_di_node = type_di_node(cx, pointee_type);
155+
let pointee_type_di_node = match pointee_type.kind() {
156+
// `&[T]` will look like `{ data_ptr: *const T, length: usize }`
157+
ty::Slice(element_type) => type_di_node(cx, *element_type),
158+
// `&str` will look like `{ data_ptr: *const u8, length: usize }`
159+
ty::Str => type_di_node(cx, cx.tcx.types.u8),
160+
161+
// `&dyn K` will look like `{ pointer: _, vtable: _}`
162+
// any Adt `Foo` containing an unsized type (eg `&[_]` or `&dyn _`)
163+
// will look like `{ data_ptr: *const Foo, length: usize }`
164+
// and thin pointers `&Foo` will just look like `*const Foo`.
165+
//
166+
// in all those cases, we just use the pointee_type
167+
_ => type_di_node(cx, pointee_type),
168+
};
156169

157170
return_if_di_node_created_in_meantime!(cx, unique_type_id);
158171

@@ -389,26 +402,11 @@ fn build_dyn_type_di_node<'ll, 'tcx>(
389402
}
390403

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

424422
let element_type_di_node = type_di_node(cx, element_type);
425423
return_if_di_node_created_in_meantime!(cx, unique_type_id);
426-
DINodeCreationResult { di_node: element_type_di_node, already_stored_in_typemap: false }
424+
let (size, align) = cx.spanned_size_and_align_of(slice_type, span);
425+
let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, -1) };
426+
let subscripts = &[subrange];
427+
let di_node = unsafe {
428+
llvm::LLVMDIBuilderCreateArrayType(
429+
DIB(cx),
430+
size.bits(),
431+
align.bits() as u32,
432+
element_type_di_node,
433+
subscripts.as_ptr(),
434+
subscripts.len() as c_uint,
435+
)
436+
};
437+
DINodeCreationResult { di_node, already_stored_in_typemap: false }
427438
}
428439

429440
/// Get the debuginfo node for the given type.
@@ -454,7 +465,7 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
454465
}
455466
ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
456467
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span),
457-
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
468+
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id, span),
458469
ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
459470
ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
460471
ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {

compiler/rustc_error_codes/src/error_codes/E0755.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ side effects or infinite loops:
2020
2121
extern "C" {
2222
#[unsafe(ffi_pure)] // ok!
23-
pub fn strlen(s: *const i8) -> isize;
23+
pub fn strlen(s: *const std::ffi::c_char) -> usize;
2424
}
2525
# fn main() {}
2626
```

compiler/rustc_error_codes/src/error_codes/E0756.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ which have no side effects except for their return value:
2121
2222
extern "C" {
2323
#[unsafe(ffi_const)] // ok!
24-
pub fn strlen(s: *const i8) -> i32;
24+
pub fn strlen(s: *const std::ffi::c_char) -> usize;
2525
}
2626
# fn main() {}
2727
```

compiler/rustc_hir/src/hir.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,93 @@ impl<'hir> Generics<'hir> {
10881088
bound_span.with_lo(bounds[bound_pos - 1].span().hi())
10891089
}
10901090
}
1091+
1092+
/// Computes the span representing the removal of a generic parameter at `param_index`.
1093+
///
1094+
/// This function identifies the correct slice of source code to delete so that the
1095+
/// remaining generic list remains syntactically valid (handling commas and brackets).
1096+
///
1097+
/// ### Examples
1098+
///
1099+
/// 1. **With a following parameter:** (Includes the trailing comma)
1100+
/// - Input: `<T, U>` (index 0)
1101+
/// - Produces span for: `T, `
1102+
///
1103+
/// 2. **With a previous parameter:** (Includes the leading comma and bounds)
1104+
/// - Input: `<T: Clone, U>` (index 1)
1105+
/// - Produces span for: `, U`
1106+
///
1107+
/// 3. **The only parameter:** (Includes the angle brackets)
1108+
/// - Input: `<T>` (index 0)
1109+
/// - Produces span for: `<T>`
1110+
///
1111+
/// 4. **Parameter with where-clause bounds:**
1112+
/// - Input: `fn foo<T, U>() where T: Copy` (index 0)
1113+
/// - Produces span for: `T, ` (The where-clause remains for other logic to handle).
1114+
pub fn span_for_param_removal(&self, param_index: usize) -> Span {
1115+
if param_index >= self.params.len() {
1116+
return self.span.shrink_to_hi();
1117+
}
1118+
1119+
let is_param_explicit = |par: &&GenericParam<'_>| match par.kind {
1120+
GenericParamKind::Type { .. }
1121+
| GenericParamKind::Const { .. }
1122+
| GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit } => true,
1123+
_ => false,
1124+
};
1125+
1126+
// Find the span of the type parameter.
1127+
if let Some(next) = self.params[param_index + 1..].iter().find(is_param_explicit) {
1128+
self.params[param_index].span.until(next.span)
1129+
} else if let Some(prev) = self.params[..param_index].iter().rfind(is_param_explicit) {
1130+
let mut prev_span = prev.span;
1131+
// Consider the span of the bounds with the previous generic parameter when there is.
1132+
if let Some(prev_bounds_span) = self.span_for_param_bounds(prev) {
1133+
prev_span = prev_span.to(prev_bounds_span);
1134+
}
1135+
1136+
// Consider the span of the bounds with the current generic parameter when there is.
1137+
prev_span.shrink_to_hi().to(
1138+
if let Some(cur_bounds_span) = self.span_for_param_bounds(&self.params[param_index])
1139+
{
1140+
cur_bounds_span
1141+
} else {
1142+
self.params[param_index].span
1143+
},
1144+
)
1145+
} else {
1146+
// Remove also angle brackets <> when there is just ONE generic parameter.
1147+
self.span
1148+
}
1149+
}
1150+
1151+
/// Returns the span of the `WherePredicate` associated with the given `GenericParam`, if any.
1152+
///
1153+
/// This looks specifically for predicates in the `where` clause that were generated
1154+
/// from the parameter definition (e.g., `T` in `where T: Bound`).
1155+
///
1156+
/// ### Example
1157+
///
1158+
/// - Input: `param` representing `T`
1159+
/// - Context: `where T: Clone + Default, U: Copy`
1160+
/// - Returns: Span of `T: Clone + Default`
1161+
fn span_for_param_bounds(&self, param: &GenericParam<'hir>) -> Option<Span> {
1162+
self.predicates
1163+
.iter()
1164+
.find(|pred| {
1165+
if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1166+
origin: PredicateOrigin::GenericParam,
1167+
bounded_ty,
1168+
..
1169+
}) = pred.kind
1170+
{
1171+
bounded_ty.span == param.span
1172+
} else {
1173+
false
1174+
}
1175+
})
1176+
.map(|pred| pred.span)
1177+
}
10911178
}
10921179

10931180
/// A single predicate in a where-clause.

compiler/rustc_hir/src/lang_items.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,14 @@ language_item_table! {
448448

449449
// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
450450
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
451+
452+
// Runtime symbols
453+
MemCpy, sym::memcpy_fn, memcpy_fn, Target::Fn, GenericRequirement::None;
454+
MemMove, sym::memmove_fn, memmove_fn, Target::Fn, GenericRequirement::None;
455+
MemSet, sym::memset_fn, memset_fn, Target::Fn, GenericRequirement::None;
456+
MemCmp, sym::memcmp_fn, memcmp_fn, Target::Fn, GenericRequirement::None;
457+
Bcmp, sym::bcmp_fn, bcmp_fn, Target::Fn, GenericRequirement::None;
458+
StrLen, sym::strlen_fn, strlen_fn, Target::Fn, GenericRequirement::None;
451459
}
452460

453461
/// The requirement imposed on the generics of a lang item

compiler/rustc_hir/src/weak_lang_items.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,29 @@ macro_rules! weak_lang_items {
2323
}
2424
}
2525

26+
macro_rules! weak_only_lang_items {
27+
($($item:ident,)*) => {
28+
pub static WEAK_ONLY_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
29+
30+
impl LangItem {
31+
pub fn is_weak_only(self) -> bool {
32+
matches!(self, $(LangItem::$item)|*)
33+
}
34+
}
35+
}
36+
}
37+
2638
weak_lang_items! {
2739
PanicImpl, rust_begin_unwind;
2840
EhPersonality, rust_eh_personality;
2941
EhCatchTypeinfo, rust_eh_catch_typeinfo;
3042
}
43+
44+
weak_only_lang_items! {
45+
MemCpy,
46+
MemMove,
47+
MemSet,
48+
MemCmp,
49+
Bcmp,
50+
StrLen,
51+
}

compiler/rustc_hir_analysis/src/delegation.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_middle::ty::{
1414
use rustc_span::{ErrorGuaranteed, Span, kw};
1515

1616
use crate::collect::ItemCtxt;
17+
use crate::errors::DelegationSelfTypeNotSpecified;
1718
use crate::hir_ty_lowering::HirTyLowerer;
1819

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

0 commit comments

Comments
 (0)