Skip to content

Commit e248841

Browse files
committed
Auto merge of #157174 - JonathanBrouwer:rollup-XgLtev4, r=JonathanBrouwer
Rollup of 8 pull requests Successful merges: - #157006 (net tests: let the OS pick the port numbers) - #157126 (Avoid redundant note when a #[derive] is already suggested) - #151690 (std: Refactor `env::var` function) - #155826 (std::process: uefi: avoid panicking in Stdio From impls.) - #156109 (Migrate libraries from ptr::slice_from_raw_parts to .cast_slice) - #156642 (`offload_kernel` macro expansion) - #156823 (Add regression test) - #157162 (elaborate_drop: Avoid as_mut.unwrap dance, empty vectors are cheap.) Failed merges: - #157173 (rustc-dev-guide subtree update)
2 parents f8a08b6 + d662f5a commit e248841

55 files changed

Lines changed: 662 additions & 266 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.

compiler/rustc_builtin_macros/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ mod format_foreign;
4242
mod global_allocator;
4343
mod iter;
4444
mod log_syntax;
45+
mod offload;
4546
mod pattern_type;
4647
mod source_util;
4748
mod test;
@@ -116,6 +117,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
116117
eii_declaration: eii::eii_declaration,
117118
eii_shared_macro: eii::eii_shared_macro,
118119
global_allocator: global_allocator::expand,
120+
offload_kernel: offload::expand_kernel,
119121
test: test::expand_test,
120122
test_case: test::expand_test_case,
121123
unsafe_eii: eii::unsafe_eii,
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
use rustc_ast::token::{Delimiter, Token, TokenKind};
2+
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
3+
use rustc_ast::{AttrItem, ast};
4+
use rustc_expand::base::{Annotatable, ExtCtxt};
5+
use rustc_session::config::Offload;
6+
use rustc_span::{Ident, Span, sym};
7+
use thin_vec::thin_vec;
8+
9+
use crate::errors;
10+
11+
fn compile_for_device(ecx: &mut ExtCtxt<'_>) -> bool {
12+
ecx.sess.opts.unstable_opts.offload.contains(&Offload::Device)
13+
}
14+
15+
fn outer_normal_attr(
16+
kind: &Box<rustc_ast::NormalAttr>,
17+
id: rustc_ast::AttrId,
18+
span: Span,
19+
) -> rustc_ast::Attribute {
20+
let style = rustc_ast::AttrStyle::Outer;
21+
let kind = rustc_ast::AttrKind::Normal(kind.clone());
22+
rustc_ast::Attribute { kind, id, style, span }
23+
}
24+
25+
fn extract_fn(
26+
item: &Annotatable,
27+
) -> Option<(ast::Visibility, ast::FnSig, Ident, ast::Generics, Option<Box<ast::Block>>)> {
28+
match item {
29+
Annotatable::Item(iitem) => match &iitem.kind {
30+
ast::ItemKind::Fn(ast::Fn { sig, ident, generics, body, .. }) => {
31+
Some((iitem.vis.clone(), sig.clone(), *ident, generics.clone(), body.clone()))
32+
}
33+
_ => None,
34+
},
35+
_ => None,
36+
}
37+
}
38+
39+
/// The `offload_kernel` macro expands the function into two separate definitions:
40+
/// one on the host to handle the call, and one on the device for executing the kernel.
41+
///
42+
/// ```
43+
/// #[offload_kernel]
44+
/// fn foo(a: &[f32], b: &[f32], c: *mut f32) {
45+
/// *c = a[0] + b[0];
46+
/// }
47+
/// ```
48+
///
49+
/// This expands to the host-side function:
50+
///
51+
/// ```
52+
/// #[unsafe(no_mangle)]
53+
/// #[inline(never)]
54+
/// fn foo(_: &[f32], _: &[f32], _: *mut f32) {
55+
/// ::core::panicking::panic("not implemented")
56+
/// }
57+
/// ```
58+
///
59+
/// And the device-side kernel:
60+
///
61+
/// ```
62+
/// #[rustc_offload_kernel]
63+
/// #[unsafe(no_mangle)]
64+
/// unsafe extern "gpu-kernel" fn foo(a: &[f32], b: &[f32], c: *mut f32) {
65+
/// *c = a[0] + b[0];
66+
/// }
67+
/// ```
68+
pub(crate) fn expand_kernel(
69+
ecx: &mut ExtCtxt<'_>,
70+
expand_span: Span,
71+
_meta_item: &ast::MetaItem,
72+
item: Annotatable,
73+
) -> Vec<Annotatable> {
74+
let dcx = ecx.sess.dcx();
75+
76+
let Some((vis, sig, ident, generics, body)) = extract_fn(&item) else {
77+
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
78+
return vec![item];
79+
};
80+
81+
let span = ecx.with_def_site_ctxt(expand_span);
82+
83+
// device function
84+
let mut device_fn = Box::new(ast::Fn {
85+
defaultness: ast::Defaultness::Implicit,
86+
sig: sig.clone(),
87+
ident,
88+
generics: generics.clone(),
89+
contract: None,
90+
body,
91+
define_opaque: None,
92+
eii_impls: Default::default(),
93+
});
94+
95+
let extern_gpu_kernel = ast::Extern::from_abi(
96+
Some(ast::StrLit {
97+
symbol: sym::gpu_kernel,
98+
suffix: None,
99+
symbol_unescaped: sym::gpu_kernel,
100+
style: ast::StrStyle::Cooked,
101+
span,
102+
}),
103+
span,
104+
);
105+
device_fn.sig.header.ext = extern_gpu_kernel;
106+
device_fn.sig.header.safety = ast::Safety::Unsafe(span);
107+
108+
// rustc_offload_kernel attr
109+
let rustc_offload_kernel_attr =
110+
Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_offload_kernel)));
111+
let rustc_offload_kernel = outer_normal_attr(
112+
&rustc_offload_kernel_attr,
113+
ecx.sess.psess.attr_id_generator.mk_attr_id(),
114+
span,
115+
);
116+
117+
// unsafe(no_mangle) attr
118+
let unsafe_item = AttrItem {
119+
unsafety: ast::Safety::Unsafe(span),
120+
path: ast::Path::from_ident(Ident::new(sym::no_mangle, span)),
121+
args: ast::AttrItemKind::Unparsed(ast::AttrArgs::Empty),
122+
tokens: None,
123+
};
124+
125+
let no_mangle_attr = Box::new(ast::NormalAttr { item: unsafe_item, tokens: None });
126+
let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
127+
let unsafe_no_mangle = outer_normal_attr(&no_mangle_attr, new_id, span);
128+
129+
let device_item = {
130+
let mut item = ecx.item(
131+
span,
132+
thin_vec![rustc_offload_kernel, unsafe_no_mangle],
133+
ast::ItemKind::Fn(device_fn),
134+
);
135+
item.vis = vis.clone();
136+
Annotatable::Item(item)
137+
};
138+
139+
// unimplemented! body
140+
let macro_expr = ecx.expr_macro_call(
141+
span,
142+
ecx.macro_call(
143+
span,
144+
ecx.path_global(
145+
span,
146+
[sym::std, sym::unimplemented].map(|s| Ident::new(s, span)).to_vec(),
147+
),
148+
Delimiter::Parenthesis,
149+
TokenStream::default(),
150+
),
151+
);
152+
let stmt = ecx.stmt_expr(macro_expr);
153+
let body = ecx.block(span, thin_vec![stmt]);
154+
155+
// host function
156+
let mut host_fn = Box::new(ast::Fn {
157+
defaultness: ast::Defaultness::Implicit,
158+
sig: sig.clone(),
159+
ident,
160+
generics: generics.clone(),
161+
contract: None,
162+
body: Some(body),
163+
define_opaque: None,
164+
eii_impls: Default::default(),
165+
});
166+
167+
for param in host_fn.sig.decl.inputs.iter_mut() {
168+
param.pat = Box::new(ecx.pat_wild(param.pat.span));
169+
}
170+
171+
// inline(never) attr
172+
let ts: Vec<TokenTree> = vec![TokenTree::Token(
173+
Token::new(TokenKind::Ident(sym::never, false.into()), span),
174+
Spacing::Joint,
175+
)];
176+
177+
let never_arg = ast::DelimArgs {
178+
dspan: DelimSpan::from_single(span),
179+
delim: Delimiter::Parenthesis,
180+
tokens: TokenStream::from_iter(ts),
181+
};
182+
183+
let inline_item = ast::AttrItem {
184+
unsafety: ast::Safety::Default,
185+
path: ast::Path::from_ident(Ident::with_dummy_span(sym::inline)),
186+
args: rustc_ast::ast::AttrItemKind::Unparsed(ast::AttrArgs::Delimited(never_arg)),
187+
tokens: None,
188+
};
189+
let inline_never_attr = Box::new(ast::NormalAttr { item: inline_item, tokens: None });
190+
191+
let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
192+
let inline_never = outer_normal_attr(&inline_never_attr, new_id, span);
193+
194+
let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
195+
let unsafe_no_mangle = outer_normal_attr(&no_mangle_attr, new_id, span);
196+
197+
let host_item = {
198+
let mut item =
199+
ecx.item(span, thin_vec![unsafe_no_mangle, inline_never], ast::ItemKind::Fn(host_fn));
200+
item.vis = vis.clone();
201+
Annotatable::Item(item)
202+
};
203+
204+
if compile_for_device(ecx) { vec![device_item] } else { vec![host_item] }
205+
}

compiler/rustc_mir_transform/src/elaborate_drop.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -842,9 +842,9 @@ where
842842
let mut values = Vec::with_capacity(adt.variants().len());
843843
let mut normal_blocks = Vec::with_capacity(adt.variants().len());
844844
let mut unwind_blocks =
845-
if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants().len())) };
845+
Vec::with_capacity(if unwind.is_cleanup() { 0 } else { adt.variants().len() });
846846
let mut dropline_blocks =
847-
if dropline.is_none() { None } else { Some(Vec::with_capacity(adt.variants().len())) };
847+
Vec::with_capacity(if dropline.is_none() { 0 } else { adt.variants().len() });
848848

849849
let mut have_otherwise_with_drop_glue = false;
850850
let mut have_otherwise = false;
@@ -880,7 +880,6 @@ where
880880
// I want to minimize the divergence between MSVC
881881
// and non-MSVC.
882882

883-
let unwind_blocks = unwind_blocks.as_mut().unwrap();
884883
let unwind_ladder = vec![Unwind::InCleanup; fields.len() + 1];
885884
let dropline_ladder: Vec<Option<BasicBlock>> = vec![None; fields.len() + 1];
886885
let halfladder =
@@ -890,7 +889,7 @@ where
890889
let (normal, _, drop_bb) = self.drop_ladder(fields, succ, unwind, dropline);
891890
normal_blocks.push(normal);
892891
if dropline.is_some() {
893-
dropline_blocks.as_mut().unwrap().push(drop_bb.unwrap());
892+
dropline_blocks.push(drop_bb.unwrap());
894893
}
895894
} else {
896895
have_otherwise = true;
@@ -911,28 +910,22 @@ where
911910
} else if !have_otherwise_with_drop_glue {
912911
normal_blocks.push(self.goto_block(succ, unwind));
913912
if let Unwind::To(unwind) = unwind {
914-
unwind_blocks.as_mut().unwrap().push(self.goto_block(unwind, Unwind::InCleanup));
913+
unwind_blocks.push(self.goto_block(unwind, Unwind::InCleanup));
915914
}
916915
} else {
917916
normal_blocks.push(self.drop_block(succ, unwind));
918917
if let Unwind::To(unwind) = unwind {
919-
unwind_blocks.as_mut().unwrap().push(self.drop_block(unwind, Unwind::InCleanup));
918+
unwind_blocks.push(self.drop_block(unwind, Unwind::InCleanup));
920919
}
921920
}
922921

923922
(
924923
self.adt_switch_block(adt, normal_blocks, &values, succ, unwind),
925924
unwind.map(|unwind| {
926-
self.adt_switch_block(
927-
adt,
928-
unwind_blocks.unwrap(),
929-
&values,
930-
unwind,
931-
Unwind::InCleanup,
932-
)
925+
self.adt_switch_block(adt, unwind_blocks, &values, unwind, Unwind::InCleanup)
933926
}),
934927
dropline.map(|dropline| {
935-
self.adt_switch_block(adt, dropline_blocks.unwrap(), &values, dropline, unwind)
928+
self.adt_switch_block(adt, dropline_blocks, &values, dropline, unwind)
936929
}),
937930
)
938931
}

compiler/rustc_span/src/symbol.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ symbols! {
10401040
global_asm,
10411041
global_registration,
10421042
globs,
1043+
gpu_kernel: "gpu-kernel",
10431044
gpu_launch_sized_workgroup_mem,
10441045
gt,
10451046
guard,
@@ -1424,6 +1425,7 @@ symbols! {
14241425
of,
14251426
off,
14261427
offload,
1428+
offload_kernel,
14271429
offset,
14281430
offset_of,
14291431
offset_of_enum,
@@ -2163,6 +2165,7 @@ symbols! {
21632165
underscore_imports,
21642166
underscore_lifetimes,
21652167
uniform_paths,
2168+
unimplemented,
21662169
unit,
21672170
universal_impl_trait,
21682171
unix,

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
448448
if let Some((msg, span)) = type_def {
449449
err.span_label(span, msg);
450450
}
451-
for note in notes {
452-
// If it has a custom `#[rustc_on_unimplemented]` note, let's display it
453-
err.note(note);
451+
// `#[rustc_on_unimplemented]` notes for derivable traits (e.g. `Debug`'s
452+
// "add `#[derive(Debug)]` to `X` or manually `impl Debug for X`") duplicate
453+
// the `consider annotating X with #[derive(..)]` suggestion that
454+
// `suggest_derive` emits below, so skip them when that suggestion will be
455+
// shown. We keep the note otherwise (e.g. when a field isn't `Debug`, so
456+
// the derive can't be suggested) to avoid leaving the diagnostic without
457+
// actionable guidance.
458+
let derive_suggestion_will_be_shown = main_trait_predicate
459+
== leaf_trait_predicate
460+
&& self.can_suggest_derive(&obligation, leaf_trait_predicate);
461+
if !derive_suggestion_will_be_shown {
462+
for note in notes {
463+
// If it has a custom `#[rustc_on_unimplemented]` note, let's display
464+
// it.
465+
err.note(note);
466+
}
454467
}
455468
if let Some(s) = parent_label {
456469
let body = obligation.cause.body_id;

library/alloc/src/alloc.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,12 @@ impl Global {
204204
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
205205
fn alloc_impl_runtime(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
206206
match layout.size() {
207-
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
207+
0 => Ok(layout.dangling_ptr().cast_slice(0)),
208208
// SAFETY: `layout` is non-zero in size,
209209
size => unsafe {
210210
let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) };
211211
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
212-
Ok(NonNull::slice_from_raw_parts(ptr, size))
212+
Ok(ptr.cast_slice(size))
213213
},
214214
}
215215
}
@@ -261,7 +261,7 @@ impl Global {
261261
if zeroed {
262262
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
263263
}
264-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
264+
Ok(ptr.cast_slice(new_size))
265265
},
266266

267267
// SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
@@ -297,7 +297,7 @@ impl Global {
297297
// SAFETY: conditions must be upheld by the caller
298298
0 => unsafe {
299299
self.deallocate(ptr, old_layout);
300-
Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
300+
Ok(new_layout.dangling_ptr().cast_slice(0))
301301
},
302302

303303
// SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
@@ -307,7 +307,7 @@ impl Global {
307307

308308
let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
309309
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
310-
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
310+
Ok(ptr.cast_slice(new_size))
311311
},
312312

313313
// SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
@@ -388,7 +388,7 @@ impl Global {
388388
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
389389
const fn alloc_impl_const(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
390390
match layout.size() {
391-
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
391+
0 => Ok(layout.dangling_ptr().cast_slice(0)),
392392
// SAFETY: `layout` is non-zero in size,
393393
size => unsafe {
394394
let raw_ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
@@ -397,7 +397,7 @@ impl Global {
397397
// SAFETY: the pointer returned by `const_allocate` is valid to write to.
398398
ptr.write_bytes(0, size);
399399
}
400-
Ok(NonNull::slice_from_raw_parts(ptr, size))
400+
Ok(ptr.cast_slice(size))
401401
},
402402
}
403403
}

0 commit comments

Comments
 (0)