authorbors <bors@rust-lang.org> 2026-06-25 22:48:30 UTC
committerbors <bors@rust-lang.org> 2026-06-25 22:48:30 UTC
log40557f6225e337d68c8d4f086557ce54135f5dd9
treead34357ff35cbcc244cdc8783802499b6d53e3be
parentbd08c9e71874a81670fe3938dbf85148e42c2b96
parentd109bb0266a90767d866725ecda219aa73aa5fce

Auto merge of #158419 - jhpratt:rollup-38sJqWx, r=jhpratt

Rollup of 10 pull requests Successful merges: - rust-lang/rust#158410 (Update LLVM for Mach-O __LINKEDIT alignment fix.) - rust-lang/rust#157397 (cmse: clear padding when crossing the secure boundary) - rust-lang/rust#158036 (Add -Zinstrument-mcount=fentry to -Zinstrument-mcount) - rust-lang/rust#158330 (llvm: use intrinsics for f16, f32 minimum/maximum) - rust-lang/rust#158359 (fix(tests): allow either branch direction in ilog_known_base) - rust-lang/rust#158067 (LLVM 23: Adapt codegen test to moved assume) - rust-lang/rust#158261 (Move part of the target checking for `#[may_dangle]` to the parser) - rust-lang/rust#158358 (Fix invalid E0609 raw pointer deref suggestion inside macros) - rust-lang/rust#158392 (delegation: add tests for defaults and infers in generics) - rust-lang/rust#158394 (Generate synthetic generic args only for delegation's child segment)

68 files changed, 1866 insertions(+), 753 deletions(-)

compiler/rustc_abi/src/layout/ty.rs+87-1
......@@ -1,7 +1,8 @@
11use std::fmt;
2use std::ops::Deref;
2use std::ops::{Deref, Range};
33
44use rustc_data_structures::intern::Interned;
5use rustc_data_structures::range_set::RangeSet;
56use rustc_macros::StableHash;
67
78use crate::layout::{FieldIdx, VariantIdx};
......@@ -282,4 +283,89 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
282283 }
283284 found
284285 }
286
287 /// The ranges of bytes that are always ignored by the representation relation of this type.
288 ///
289 /// In other words, for any sequence of bytes, if we reset the these padding bytes to uninit,
290 /// then these two sequences of bytes represent the same value (or they are both invalid).
291 /// This is the "guaranteed" padding. There may be more bytes that are padding for some
292 /// but not all variants of this type; those are not included.
293 /// (E.g. `Option<i8>` has no guaranteed padding so the empty range set is returned, but its `None` value still has padding).
294 pub fn padding_ranges<C>(&self, cx: &C) -> Vec<Range<Size>>
295 where
296 Ty: TyAbiInterface<'a, C> + Copy,
297 {
298 let mut data = RangeSet::new();
299 self.add_data_ranges(cx, Size::ZERO, &mut data);
300
301 // Find gaps between the data ranges.
302 let mut uninit_ranges = Vec::new();
303 let mut covered_until = Size::ZERO;
304 for &(offset, size) in data.0.iter() {
305 if offset > covered_until {
306 uninit_ranges.push(covered_until..offset);
307 }
308 covered_until = Ord::max(covered_until, offset + size);
309 }
310
311 // Add trailing padding.
312 if self.size > covered_until {
313 uninit_ranges.push(covered_until..self.size);
314 }
315
316 uninit_ranges
317 }
318
319 /// Extend `out` with all ranges of bytes that *may* carry relevant data for values of this type.
320 /// For enums and unions there are offsets that are initialized for some
321 /// variants but not for others; those offset *will* get added to `out`.
322 fn add_data_ranges<C>(self, cx: &C, base_offset: Size, out: &mut RangeSet<Size>)
323 where
324 Ty: TyAbiInterface<'a, C> + Copy,
325 {
326 if self.is_zst() {
327 return;
328 }
329
330 match &self.variants {
331 Variants::Empty => { /* done */ }
332 Variants::Single { index: _ } => match &self.fields {
333 FieldsShape::Primitive => {
334 out.add_range(base_offset, self.size);
335 }
336 &FieldsShape::Union(field_count) => {
337 for field in 0..field_count.get() {
338 let field = self.field(cx, field);
339 field.add_data_ranges(cx, base_offset, out);
340 }
341 }
342 &FieldsShape::Array { stride, count } => {
343 let elem = self.field(cx, 0);
344
345 // For scalars we know there is no padding between the elements,
346 // so the entire array is a single big data range.
347 if elem.backend_repr.is_scalar() {
348 out.add_range(base_offset, elem.size * count);
349 } else {
350 // FIXME: this is really inefficient for large arrays.
351 for idx in 0..count {
352 elem.add_data_ranges(cx, base_offset + idx * stride, out);
353 }
354 }
355 }
356 FieldsShape::Arbitrary { offsets, in_memory_order: _ } => {
357 for (field, &offset) in offsets.iter_enumerated() {
358 let field = self.field(cx, field.as_usize());
359 field.add_data_ranges(cx, base_offset + offset, out);
360 }
361 }
362 },
363 Variants::Multiple { variants, .. } => {
364 for variant in variants.indices() {
365 let variant = self.for_variant(cx, variant);
366 variant.add_data_ranges(cx, base_offset, out);
367 }
368 }
369 }
370 }
285371}
compiler/rustc_abi/src/lib.rs+1-1
......@@ -792,7 +792,7 @@ impl FromStr for Endian {
792792}
793793
794794/// Size of a type in bytes.
795#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
795#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
796796#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash))]
797797pub struct Size {
798798 raw: u64,
compiler/rustc_attr_parsing/src/attributes/semantics.rs+7-1
......@@ -1,11 +1,17 @@
11use rustc_feature::AttributeStability;
2use rustc_hir::target::GenericParamKind;
23
34use super::prelude::*;
45
56pub(crate) struct MayDangleParser;
67impl NoArgsAttributeParser for MayDangleParser {
78 const PATH: &[Symbol] = &[sym::may_dangle];
8 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
9 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
10 Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: false }),
11 Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: true }),
12 Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }),
13 Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: true }),
14 ]);
915 const STABILITY: AttributeStability = unstable!(dropck_eyepatch);
1016 const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle;
1117}
compiler/rustc_attr_parsing/src/target_checking.rs+1
......@@ -416,6 +416,7 @@ pub(crate) fn allowed_targets_applied(
416416
417417 // ensure a consistent order
418418 target_strings.sort();
419 target_strings.dedup();
419420
420421 // If there is now only 1 target left, show that as the only possible target
421422 let only_target = target_strings.len() == 1;
compiler/rustc_codegen_llvm/src/attributes.rs+25-15
......@@ -7,7 +7,9 @@ use rustc_middle::middle::codegen_fn_attrs::{
77 TargetFeature,
88};
99use rustc_middle::ty::{self, Instance, TyCtxt};
10use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
10use rustc_session::config::{
11 BranchProtection, FunctionReturn, InstrumentMcount, OptLevel, PAuthKey, PacRet,
12};
1113use rustc_span::sym;
1214use rustc_symbol_mangling::mangle_internal_symbol;
1315use rustc_target::spec::{Arch, FramePointer, SanitizerSet, StackProbeType, StackProtector};
......@@ -177,7 +179,7 @@ pub(crate) fn frame_pointer(sess: &Session) -> FramePointer {
177179 let opts = &sess.opts;
178180 // "mcount" function relies on stack pointer.
179181 // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
180 if opts.unstable_opts.instrument_mcount {
182 if opts.unstable_opts.instrument_mcount == InstrumentMcount::Mcount {
181183 fp.ratchet(FramePointer::Always);
182184 }
183185 fp.ratchet(opts.cg.force_frame_pointers);
......@@ -214,7 +216,7 @@ fn instrument_function_attr<'ll>(
214216 instrument_fn: InstrumentFnAttr,
215217) -> SmallVec<[&'ll Attribute; 4]> {
216218 let mut attrs = SmallVec::new();
217 if sess.opts.unstable_opts.instrument_mcount {
219 if sess.opts.unstable_opts.instrument_mcount != InstrumentMcount::Disabled {
218220 // Similar to `clang -pg` behavior. Handled by the
219221 // `post-inline-ee-instrument` LLVM pass.
220222
......@@ -224,18 +226,26 @@ fn instrument_function_attr<'ll>(
224226 };
225227
226228 if instrument_entry {
227 // The function name varies on platforms.
228 // See test/CodeGen/mcount.c in clang.
229 let mcount_name = match &sess.target.llvm_mcount_intrinsic {
230 Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
231 None => sess.target.mcount.as_ref(),
232 };
233
234 attrs.push(llvm::CreateAttrStringValue(
235 cx.llcx,
236 "instrument-function-entry-inlined",
237 mcount_name,
238 ));
229 match sess.opts.unstable_opts.instrument_mcount {
230 InstrumentMcount::Mcount => {
231 // The function name varies on platforms.
232 // See test/CodeGen/mcount.c in clang.
233 let mcount_name = match &sess.target.llvm_mcount_intrinsic {
234 Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
235 None => sess.target.mcount.as_ref(),
236 };
237
238 attrs.push(llvm::CreateAttrStringValue(
239 cx.llcx,
240 "instrument-function-entry-inlined",
241 mcount_name,
242 ));
243 }
244 InstrumentMcount::Fentry => {
245 attrs.push(llvm::CreateAttrStringValue(cx.llcx, "fentry-call", "true"));
246 }
247 InstrumentMcount::Disabled => {}
248 }
239249 }
240250 }
241251 if let Some(options) = &sess.opts.unstable_opts.instrument_xray {
compiler/rustc_codegen_llvm/src/intrinsic.rs+4-4
......@@ -114,17 +114,17 @@ fn call_simple_intrinsic<'ll, 'tcx>(
114114 sym::fmuladdf64 => ("llvm.fmuladd", &[bx.type_f64()]),
115115 sym::fmuladdf128 => ("llvm.fmuladd", &[bx.type_f128()]),
116116
117 sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
118 sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
117119 // FIXME: LLVM currently mis-compile those intrinsics, re-enable them
118120 // when llvm/llvm-project#{139380,139381,140445} are fixed.
119 //sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
120 //sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
121121 //sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]),
122122 //sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]),
123123 //
124 sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
125 sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
124126 // FIXME: LLVM currently mis-compile those intrinsics, re-enable them
125127 // when llvm/llvm-project#{139380,139381,140445} are fixed.
126 //sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
127 //sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
128128 //sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]),
129129 //sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]),
130130 //
compiler/rustc_codegen_ssa/src/back/link.rs+3-3
......@@ -35,8 +35,8 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
3535use rustc_middle::middle::dependency_format::Linkage;
3636use rustc_middle::middle::exported_symbols::SymbolExportKind;
3737use rustc_session::config::{
38 self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
39 OutputType, PrintKind, SplitDwarfKind, Strip,
38 self, CFGuard, CrateType, DebugInfo, InstrumentMcount, LinkerFeaturesCli, OutFileName,
39 OutputFilenames, OutputType, PrintKind, SplitDwarfKind, Strip,
4040};
4141use rustc_session::lint::builtin::LINKER_MESSAGES;
4242use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
......@@ -2953,7 +2953,7 @@ fn add_order_independent_options(
29532953 cmd.pgo_gen();
29542954 }
29552955
2956 if sess.opts.unstable_opts.instrument_mcount {
2956 if sess.opts.unstable_opts.instrument_mcount != InstrumentMcount::Disabled {
29572957 cmd.enable_profiling();
29582958 }
29592959
compiler/rustc_codegen_ssa/src/mir/block.rs+71-2
......@@ -1,6 +1,9 @@
11use std::cmp;
2use std::ops::Range;
23
3use rustc_abi::{Align, BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange};
4use rustc_abi::{
5 Align, ArmCall, BackendRepr, CanonAbi, ExternAbi, HasDataLayout, Reg, Size, WrappingRange,
6};
47use rustc_ast as ast;
58use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
69use rustc_data_structures::packed::Pu128;
......@@ -597,6 +600,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
597600 }
598601 ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"),
599602 };
603
604 if self.fn_abi.conv == CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) {
605 // The return value of an `extern "cmse-nonsecure-entry"` function crosses the
606 // secure boundary. Zero padding bytes so information does not leak.
607 //
608 // This only zeroes "guaranteed" padding. There may be more bytes that are
609 // padding for some but not all variants of this type; those are not zeroed.
610 //
611 // Returning a value with value-dependent padding will instead trigger a lint.
612 let ret_layout = self.fn_abi.ret.layout;
613 let uninit_ranges = ret_layout.padding_ranges(bx.cx());
614 self.zero_byte_ranges(bx, llslot, ret_layout.size, &uninit_ranges);
615 }
616
600617 load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi)
601618 }
602619 };
......@@ -1341,6 +1358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13411358
13421359 self.codegen_argument(
13431360 bx,
1361 fn_abi.conv,
13441362 op,
13451363 by_move,
13461364 &mut llargs,
......@@ -1351,6 +1369,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13511369 let num_untupled = untuple.map(|tup| {
13521370 self.codegen_arguments_untupled(
13531371 bx,
1372 fn_abi.conv,
13541373 &tup.node,
13551374 &mut llargs,
13561375 &fn_abi.args[first_args.len()..],
......@@ -1380,6 +1399,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13801399 let last_arg = fn_abi.args.last().unwrap();
13811400 self.codegen_argument(
13821401 bx,
1402 fn_abi.conv,
13831403 location,
13841404 /* by_move */ false,
13851405 &mut llargs,
......@@ -1696,9 +1716,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16961716 }
16971717 }
16981718
1719 fn zero_byte_ranges(
1720 &mut self,
1721 bx: &mut Bx,
1722 ptr: Bx::Value,
1723 limit: Size,
1724 ranges: &[Range<Size>],
1725 ) {
1726 let zero = bx.const_u8(0);
1727
1728 for range in ranges {
1729 let end = cmp::min(range.end, limit);
1730 if range.start >= end {
1731 continue;
1732 }
1733 let offset = bx.const_usize(range.start.bytes());
1734 let len = bx.const_usize((end - range.start).bytes());
1735 let ptr = bx.inbounds_ptradd(ptr, offset);
1736 bx.memset(ptr, zero, len, Align::ONE, MemFlags::empty());
1737 }
1738 }
1739
16991740 fn codegen_argument(
17001741 &mut self,
17011742 bx: &mut Bx,
1743 conv: CanonAbi,
17021744 op: OperandRef<'tcx, Bx::Value>,
17031745 by_move: bool,
17041746 llargs: &mut Vec<Bx::Value>,
......@@ -1822,6 +1864,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18221864 MemFlags::empty(),
18231865 None,
18241866 );
1867
1868 // The arguments of an `extern "cmse-nonsecure-call"` function cross the secure
1869 // boundary. Zero padding bytes so information does not leak.
1870 //
1871 // This only zeroes "guaranteed" padding. There may be more bytes that are
1872 // padding for some but not all variants of this type; those are not zeroed.
1873 //
1874 // Passing an argument with value-dependent padding will instead trigger a lint.
1875 if conv == CanonAbi::Arm(ArmCall::CCmseNonSecureCall) {
1876 self.zero_byte_ranges(
1877 bx,
1878 llscratch,
1879 Size::from_bytes(copy_bytes),
1880 &arg.layout.padding_ranges(bx.cx()),
1881 );
1882 }
1883
18251884 // ...and then load it with the ABI type.
18261885 llval = load_cast(bx, cast, llscratch, scratch_align);
18271886 bx.lifetime_end(llscratch, scratch_size);
......@@ -1848,6 +1907,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18481907 fn codegen_arguments_untupled(
18491908 &mut self,
18501909 bx: &mut Bx,
1910 conv: CanonAbi,
18511911 operand: &mir::Operand<'tcx>,
18521912 llargs: &mut Vec<Bx::Value>,
18531913 args: &[ArgAbi<'tcx, Ty<'tcx>>],
......@@ -1867,6 +1927,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18671927 let field = bx.load_operand(field_ptr);
18681928 self.codegen_argument(
18691929 bx,
1930 conv,
18701931 field,
18711932 by_move,
18721933 llargs,
......@@ -1878,7 +1939,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18781939 // If the tuple is immediate, the elements are as well.
18791940 for i in 0..tuple.layout.fields.count() {
18801941 let op = tuple.extract_field(self, bx, i);
1881 self.codegen_argument(bx, op, by_move, llargs, &args[i], lifetime_ends_after_call);
1942 self.codegen_argument(
1943 bx,
1944 conv,
1945 op,
1946 by_move,
1947 llargs,
1948 &args[i],
1949 lifetime_ends_after_call,
1950 );
18821951 }
18831952 }
18841953 tuple.layout.fields.count()
compiler/rustc_const_eval/src/interpret/validity.rs+3-51
......@@ -345,55 +345,7 @@ fn write_path(out: &mut String, path: &[PathElem<'_>]) {
345345 }
346346}
347347
348/// Represents a set of `Size` values as a sorted list of ranges.
349// These are (offset, length) pairs, and they are sorted and mutually disjoint,
350// and never adjacent (i.e. there's always a gap between two of them).
351#[derive(Debug, Clone)]
352pub struct RangeSet(Vec<(Size, Size)>);
353
354impl RangeSet {
355 fn add_range(&mut self, offset: Size, size: Size) {
356 if size.bytes() == 0 {
357 // No need to track empty ranges.
358 return;
359 }
360 let v = &mut self.0;
361 // We scan for a partition point where the left partition is all the elements that end
362 // strictly before we start. Those are elements that are too "low" to merge with us.
363 let idx =
364 v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset);
365 // Now we want to either merge with the first element of the second partition, or insert ourselves before that.
366 if let Some(&(other_offset, other_size)) = v.get(idx)
367 && offset + size >= other_offset
368 {
369 // Their end is >= our start (otherwise it would not be in the 2nd partition) and
370 // our end is >= their start. This means we can merge the ranges.
371 let new_start = other_offset.min(offset);
372 let mut new_end = (other_offset + other_size).max(offset + size);
373 // We grew to the right, so merge with overlapping/adjacent elements.
374 // (We also may have grown to the left, but that can never make us adjacent with
375 // anything there since we selected the first such candidate via `partition_point`.)
376 let mut scan_right = 1;
377 while let Some(&(next_offset, next_size)) = v.get(idx + scan_right)
378 && new_end >= next_offset
379 {
380 // Increase our size to absorb the next element.
381 new_end = new_end.max(next_offset + next_size);
382 // Look at the next element.
383 scan_right += 1;
384 }
385 // Update the element we grew.
386 v[idx] = (new_start, new_end - new_start);
387 // Remove the elements we absorbed (if any).
388 if scan_right > 1 {
389 drop(v.drain((idx + 1)..(idx + scan_right)));
390 }
391 } else {
392 // Insert new element.
393 v.insert(idx, (offset, size));
394 }
395 }
396}
348pub type RangeSet = rustc_data_structures::range_set::RangeSet<Size>;
397349
398350struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
399351 /// The `path` may be pushed to, but the part that is present when a function
......@@ -1194,7 +1146,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
11941146 assert!(layout.is_sized(), "there are no unsized unions");
11951147 let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env);
11961148 return M::cached_union_data_range(ecx, layout.ty, || {
1197 let mut out = RangeSet(Vec::new());
1149 let mut out = RangeSet::new();
11981150 union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
11991151 out
12001152 });
......@@ -1644,7 +1596,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
16441596 ctfe_mode,
16451597 ecx,
16461598 reset_provenance_and_padding,
1647 data_bytes: reset_padding.then_some(RangeSet(Vec::new())),
1599 data_bytes: reset_padding.then_some(RangeSet::new()),
16481600 may_dangle: start_in_may_dangle,
16491601 };
16501602 v.visit_value(val)?;
compiler/rustc_data_structures/src/lib.rs+1
......@@ -68,6 +68,7 @@ pub mod obligation_forest;
6868pub mod owned_slice;
6969pub mod packed;
7070pub mod profiling;
71pub mod range_set;
7172pub mod sharded;
7273pub mod small_c_str;
7374pub mod snapshot_map;
compiler/rustc_data_structures/src/range_set.rs created+59
......@@ -0,0 +1,59 @@
1/// Represents a set of `Size` values as a sorted list of ranges.
2///
3/// These are (offset, length) pairs, and they are sorted and mutually disjoint,
4/// and never adjacent (i.e. there's always a gap between two of them).
5#[derive(Debug, Clone)]
6pub struct RangeSet<T>(pub Vec<(T, T)>);
7
8impl<T> RangeSet<T>
9where
10 T: Copy + Ord + Default,
11 T: core::ops::Add<Output = T>,
12 T: core::ops::Sub<Output = T>,
13{
14 pub fn new() -> Self {
15 Self(Vec::new())
16 }
17
18 pub fn add_range(&mut self, offset: T, size: T) {
19 if size == T::default() {
20 // No need to track empty ranges.
21 return;
22 }
23 let v = &mut self.0;
24 // We scan for a partition point where the left partition is all the elements that end
25 // strictly before we start. Those are elements that are too "low" to merge with us.
26 let idx =
27 v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset);
28 // Now we want to either merge with the first element of the second partition, or insert ourselves before that.
29 if let Some(&(other_offset, other_size)) = v.get(idx)
30 && offset + size >= other_offset
31 {
32 // Their end is >= our start (otherwise it would not be in the 2nd partition) and
33 // our end is >= their start. This means we can merge the ranges.
34 let new_start = other_offset.min(offset);
35 let mut new_end = (other_offset + other_size).max(offset + size);
36 // We grew to the right, so merge with overlapping/adjacent elements.
37 // (We also may have grown to the left, but that can never make us adjacent with
38 // anything there since we selected the first such candidate via `partition_point`.)
39 let mut scan_right = 1;
40 while let Some(&(next_offset, next_size)) = v.get(idx + scan_right)
41 && new_end >= next_offset
42 {
43 // Increase our size to absorb the next element.
44 new_end = new_end.max(next_offset + next_size);
45 // Look at the next element.
46 scan_right += 1;
47 }
48 // Update the element we grew.
49 v[idx] = (new_start, new_end - new_start);
50 // Remove the elements we absorbed (if any).
51 if scan_right > 1 {
52 drop(v.drain((idx + 1)..(idx + scan_right)));
53 }
54 } else {
55 // Insert new element.
56 v.insert(idx, (offset, size));
57 }
58 }
59}
compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs+4-7
......@@ -6,7 +6,7 @@ use rustc_errors::{
66};
77use rustc_hir::def::{DefKind, Res};
88use rustc_hir::def_id::DefId;
9use rustc_hir::{self as hir, DelegationInfo, GenericArg};
9use rustc_hir::{self as hir, GenericArg};
1010use rustc_middle::ty::{
1111 self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty,
1212};
......@@ -431,15 +431,12 @@ pub(crate) fn check_generic_arg_count(
431431 }
432432
433433 let tcx = cx.tcx();
434 let parent_def = tcx.hir_get_parent_item(seg.hir_id).def_id;
435434
436435 // Suppress this warning for delegations as it is compiler generated and lifetimes are
437436 // propagated while late-bound lifetimes may be present.
438 let explicit_late_bound = match tcx.hir_opt_delegation_info(parent_def) {
439 Some(DelegationInfo { child_seg_id, .. }) if seg.hir_id == *child_seg_id => {
440 ExplicitLateBound::No
441 }
442 _ => prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos),
437 let explicit_late_bound = match tcx.hir_is_delegation_child_segment(seg) {
438 true => ExplicitLateBound::No,
439 false => prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos),
443440 };
444441
445442 let mut invalid_args = vec![];
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+3-1
......@@ -716,6 +716,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
716716 generic_args: &'a GenericArgs<'tcx>,
717717 span: Span,
718718 infer_args: bool,
719 create_synth_args: bool,
719720 incorrect_args: &'a Result<(), GenericArgCountMismatch>,
720721 }
721722
......@@ -828,7 +829,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
828829 .instantiate(tcx, preceding_args)
829830 .skip_norm_wip()
830831 .into()
831 } else if synthetic {
832 } else if self.create_synth_args && synthetic {
832833 Ty::new_param(tcx, param.index, param.name).into()
833834 } else if infer_args {
834835 self.lowerer.ty_infer(Some(param), self.span).into()
......@@ -868,6 +869,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
868869 span,
869870 generic_args: segment.args(),
870871 infer_args: segment.infer_args,
872 create_synth_args: tcx.hir_is_delegation_child_segment(segment),
871873 incorrect_args: &arg_count.correct,
872874 };
873875
compiler/rustc_hir_typeck/src/expr.rs+3
......@@ -3159,6 +3159,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31593159
31603160 fn suggest_first_deref_field(&self, err: &mut Diag<'_>, base: &hir::Expr<'_>, field: Ident) {
31613161 err.span_label(field.span, "unknown field");
3162 if base.span.from_expansion() || field.span.from_expansion() {
3163 return;
3164 }
31623165 let val = if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
31633166 && base.len() < 20
31643167 {
compiler/rustc_interface/src/tests.rs+6-6
......@@ -13,11 +13,11 @@ use rustc_session::config::{
1313 AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CodegenRetagOptions, CoverageLevel,
1414 CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
1515 Externs, FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input,
16 InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
17 MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, OutputType, OutputTypes,
18 PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
19 SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, build_configuration,
20 build_session_options, rustc_optgroups,
16 InstrumentCoverage, InstrumentMcount, InstrumentXRay, LinkSelfContained, LinkerPluginLto,
17 LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName,
18 OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius,
19 ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
20 build_configuration, build_session_options, rustc_optgroups,
2121};
2222use rustc_session::lint::Level;
2323use rustc_session::search_paths::SearchPath;
......@@ -834,7 +834,7 @@ fn test_unstable_options_tracking_hash() {
834834 tracked!(inline_mir, Some(true));
835835 tracked!(inline_mir_hint_threshold, Some(123));
836836 tracked!(inline_mir_threshold, Some(123));
837 tracked!(instrument_mcount, true);
837 tracked!(instrument_mcount, InstrumentMcount::Mcount);
838838 tracked!(instrument_xray, Some(InstrumentXRay::default()));
839839 tracked!(link_directives, false);
840840 tracked!(link_only, true);
compiler/rustc_middle/src/hir/map.rs+7
......@@ -879,6 +879,13 @@ impl<'tcx> TyCtxt<'tcx> {
879879 self.hir_opt_delegation_info(delegation_id).expect("processing delegation")
880880 }
881881
882 pub fn hir_is_delegation_child_segment(self, segment: &PathSegment<'_>) -> bool {
883 let parent_def = self.hir_get_parent_item(segment.hir_id).def_id;
884
885 self.hir_opt_delegation_info(parent_def)
886 .is_some_and(|info| info.child_seg_id == segment.hir_id)
887 }
888
882889 #[inline]
883890 fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
884891 match self.hir_node(id) {
compiler/rustc_passes/src/check_attr.rs+15-8
......@@ -24,8 +24,9 @@ use rustc_hir::def::DefKind;
2424use rustc_hir::def_id::LocalModDefId;
2525use rustc_hir::intravisit::{self, Visitor};
2626use rustc_hir::{
27 self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParamKind, HirId,
28 Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, find_attr,
27 self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam,
28 GenericParamKind, HirId, Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem,
29 find_attr,
2930};
3031use rustc_macros::Diagnostic;
3132use rustc_middle::hir::nested_filter;
......@@ -1121,12 +1122,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
11211122
11221123 /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
11231124 fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) {
1124 if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
1125 && matches!(
1126 param.kind,
1127 hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
1128 )
1129 && matches!(param.source, hir::GenericParamSource::Generics)
1125 let hir::Node::GenericParam(
1126 param @ GenericParam {
1127 kind: hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. },
1128 ..
1129 },
1130 ) = self.tcx.hir_node(hir_id)
1131 else {
1132 self.dcx().delayed_bug("Checked in attr parser");
1133 return;
1134 };
1135
1136 if matches!(param.source, hir::GenericParamSource::Generics)
11301137 && let parent_hir_id = self.tcx.parent_hir_id(hir_id)
11311138 && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
11321139 && let hir::ItemKind::Impl(impl_) = item.kind
compiler/rustc_session/src/config.rs+17-5
......@@ -255,6 +255,17 @@ pub enum AnnotateMoves {
255255 Enabled(Option<u64>),
256256}
257257
258/// The different settings that the `-Z Instrument-mcount` flag can have.
259#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
260pub enum InstrumentMcount {
261 /// `-Z instrument-mcount=no`
262 Disabled,
263 /// `-Z instrument-mcount=yes`
264 Mcount,
265 /// `-Z instrument-mcount=fentry`
266 Fentry,
267}
268
258269/// Settings for `-Z instrument-xray` flag.
259270#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
260271pub struct InstrumentXRay {
......@@ -3085,11 +3096,11 @@ pub(crate) mod dep_tracking {
30853096 use super::{
30863097 AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CodegenRetagOptions,
30873098 CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
3088 FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
3089 LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel,
3090 OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks,
3091 SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
3092 WasiExecModel,
3099 FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentMcount, InstrumentXRay,
3100 LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload,
3101 OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
3102 ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
3103 SymbolManglingVersion, WasiExecModel,
30933104 };
30943105 use crate::lint;
30953106 use crate::utils::NativeLib;
......@@ -3151,6 +3162,7 @@ pub(crate) mod dep_tracking {
31513162 TlsModel,
31523163 InstrumentCoverage,
31533164 CoverageOptions,
3165 InstrumentMcount,
31543166 InstrumentXRay,
31553167 CrateType,
31563168 MergeFunctions,
compiler/rustc_session/src/options.rs+16-1
......@@ -804,6 +804,8 @@ mod desc {
804804 pub(crate) const parse_coverage_options: &str = "`block` | `branch` | `condition`";
805805 pub(crate) const parse_codegen_retag_options: &str =
806806 "either no value or a comma-separated list of settings: `no-precise-im`, `no-precise-pin`";
807 pub(crate) const parse_instrument_mcount: &str =
808 "either a boolean (`yes`, `no`, `on`, `off`, etc), or `fentry` on supported targets.";
807809 pub(crate) const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
808810 pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
809811 pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
......@@ -1583,6 +1585,19 @@ pub mod parse {
15831585 true
15841586 }
15851587
1588 pub(crate) fn parse_instrument_mcount(slot: &mut InstrumentMcount, v: Option<&str>) -> bool {
1589 let mut use_mcount = false;
1590 if parse_bool(&mut use_mcount, v) {
1591 *slot = if use_mcount { InstrumentMcount::Mcount } else { InstrumentMcount::Disabled };
1592 true
1593 } else if let Some("fentry") = v {
1594 *slot = InstrumentMcount::Fentry;
1595 true
1596 } else {
1597 false
1598 }
1599 }
1600
15861601 pub(crate) fn parse_instrument_xray(
15871602 slot: &mut Option<InstrumentXRay>,
15881603 v: Option<&str>,
......@@ -2453,7 +2468,7 @@ options! {
24532468 "a default MIR inlining threshold (default: 50)"),
24542469 input_stats: bool = (false, parse_bool, [UNTRACKED],
24552470 "print some statistics about AST and HIR (default: no)"),
2456 instrument_mcount: bool = (false, parse_bool, [TRACKED],
2471 instrument_mcount: InstrumentMcount = (InstrumentMcount::Disabled, parse_instrument_mcount, [TRACKED],
24572472 "insert function instrument code for mcount-based tracing (default: no)"),
24582473 instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
24592474 "insert function instrument code for XRay-based tracing (default: no)
compiler/rustc_session/src/session.rs+7-1
......@@ -38,7 +38,7 @@ use crate::code_stats::CodeStats;
3838pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
3939use crate::config::{
4040 self, Cfg, CheckCfg, CoverageLevel, CoverageOptions, CrateType, DebugInfo, ErrorOutputType,
41 FunctionReturn, Input, InstrumentCoverage, OptLevel, OutFileName, OutputType,
41 FunctionReturn, Input, InstrumentCoverage, InstrumentMcount, OptLevel, OutFileName, OutputType,
4242 SwitchWithOptPath,
4343};
4444use crate::filesearch::FileSearch;
......@@ -1340,6 +1340,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
13401340 }
13411341 }
13421342
1343 if sess.opts.unstable_opts.instrument_mcount == InstrumentMcount::Fentry
1344 && !sess.target.options.supports_fentry
1345 {
1346 sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "fentry".to_string() });
1347 }
1348
13431349 if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray {
13441350 sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() });
13451351 }
compiler/rustc_target/src/spec/json.rs+3
......@@ -223,6 +223,7 @@ impl Target {
223223 forward!(supports_stack_protector);
224224 forward!(small_data_threshold_support);
225225 forward!(entry_name);
226 forward!(supports_fentry);
226227 forward!(supports_xray);
227228
228229 // we're going to run `update_from_cli`, but that won't change the target's AbiMap
......@@ -407,6 +408,7 @@ impl ToJson for Target {
407408 target_option_val!(small_data_threshold_support);
408409 target_option_val!(entry_name);
409410 target_option_val!(entry_abi);
411 target_option_val!(supports_fentry);
410412 target_option_val!(supports_xray);
411413
412414 // Serializing `-Clink-self-contained` needs a dynamic key to support the
......@@ -626,6 +628,7 @@ struct TargetSpecJson {
626628 supports_stack_protector: Option<bool>,
627629 small_data_threshold_support: Option<SmallDataThresholdSupport>,
628630 entry_name: Option<StaticCow<str>>,
631 supports_fentry: Option<bool>,
629632 supports_xray: Option<bool>,
630633 entry_abi: Option<ExternAbiWrapper>,
631634}
compiler/rustc_target/src/spec/mod.rs+4
......@@ -2688,6 +2688,9 @@ pub struct TargetOptions {
26882688 /// Default value is `CanonAbi::C`
26892689 pub entry_abi: CanonAbi,
26902690
2691 /// Whether the target supports fentry instrumentation.
2692 pub supports_fentry: bool,
2693
26912694 /// Whether the target supports XRay instrumentation.
26922695 pub supports_xray: bool,
26932696
......@@ -2929,6 +2932,7 @@ impl Default for TargetOptions {
29292932 supports_stack_protector: true,
29302933 entry_name: "main".into(),
29312934 entry_abi: CanonAbi::C,
2935 supports_fentry: false,
29322936 supports_xray: false,
29332937 default_address_space: rustc_abi::AddressSpace::ZERO,
29342938 small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs+1
......@@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
2222 base.supported_sanitizers = SanitizerSet::ADDRESS;
2323 base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
2424 base.stack_probes = StackProbeType::Inline;
25 base.supports_fentry = true;
2526
2627 Target {
2728 llvm_target: "i686-unknown-linux-gnu".into(),
compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs+1
......@@ -12,6 +12,7 @@ pub(crate) fn target() -> Target {
1212 base.max_atomic_width = Some(64);
1313 base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
1414 base.stack_probes = StackProbeType::Inline;
15 base.supports_fentry = true;
1516 // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
1617 base.crt_static_default = true;
1718
compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs+1
......@@ -12,6 +12,7 @@ pub(crate) fn target() -> Target {
1212 base.stack_probes = StackProbeType::Inline;
1313 base.supported_sanitizers =
1414 SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
15 base.supports_fentry = true;
1516
1617 Target {
1718 llvm_target: "s390x-unknown-linux-gnu".into(),
compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs+1
......@@ -13,6 +13,7 @@ pub(crate) fn target() -> Target {
1313 base.stack_probes = StackProbeType::Inline;
1414 base.supported_sanitizers =
1515 SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
16 base.supports_fentry = true;
1617
1718 Target {
1819 llvm_target: "s390x-unknown-linux-musl".into(),
compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs+1
......@@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
2020 rustc_abi: Some(RustcAbi::Softfloat),
2121 stack_probes: StackProbeType::Inline,
2222 supported_sanitizers: SanitizerSet::KERNELADDRESS,
23 supports_fentry: true,
2324 ..Default::default()
2425 };
2526
compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs+1
......@@ -19,6 +19,7 @@ pub(crate) fn target() -> Target {
1919 | SanitizerSet::SAFESTACK
2020 | SanitizerSet::THREAD
2121 | SanitizerSet::REALTIME;
22 base.supports_fentry = true;
2223 base.supports_xray = true;
2324
2425 Target {
compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs+1
......@@ -15,6 +15,7 @@ pub(crate) fn target() -> Target {
1515 | SanitizerSet::LEAK
1616 | SanitizerSet::MEMORY
1717 | SanitizerSet::THREAD;
18 base.supports_fentry = true;
1819 base.supports_xray = true;
1920 // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
2021 base.crt_static_default = true;
compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs+1
......@@ -10,6 +10,7 @@ pub(crate) fn target() -> Target {
1010 base.linker_flavor = LinkerFlavor::Gnu(Cc::No, Lld::Yes);
1111 base.linker = Some("rust-lld".into());
1212 base.panic_strategy = PanicStrategy::Abort;
13 base.supports_fentry = true;
1314
1415 Target {
1516 llvm_target: "x86_64-unknown-linux-none".into(),
src/doc/unstable-book/src/compiler-flags/instrument-mcount.md created+143
......@@ -0,0 +1,143 @@
1# `instrument-mcount`
2
3Insert calls to a counting function at the entry of each function. Traditionally, the name of this function was
4mcount, but the exact name may vary depending on target and option usage.
5
6The counting function is a special function which does not typically follow a target's ABI. It generally takes
7two arguments, the address of the calling function and the address of the called function. It was intially used
8to profile applications, but has expanded to other usages (for example [ftrace on Linux](https://docs.kernel.org/trace/ftrace.html)).
9
10Supported options:
11
12 - `no`, `n`, `off`: Do no enable instrumentation. The default option. This requires, and enables frame pointer generation.
13 - `yes`, `y`, `on`: Enable mcount based function instrumentation.
14 - `fentry`: Enable fentry based function instrument, where supported. The calling conventions for this are different than mcount, with less overhead, and no frame pointer requirements. This counting function is always named `__fentry__`. This is only available on x86 and s390x targets.
15
16|target |mcount function|supports fentry|ABI notes|
17|--- |--- |--- |--- |
18|aarch64-apple-darwin | `\u{1}mcount` | | |
19|aarch64-pc-windows-msvc | `mcount` | | |
20|aarch64-unknown-linux-gnu| `_mcount` | | |
21|i686-pc-windows-msvc | `mcount` | x| |
22|i686-unknown-linux-gnu | `mcount` | x| |
23|x86_64-pc-windows-gnu | `_mcount` | x| |
24|x86_64-pc-windows-msvc | `mcount` | x| |
25|x86_64-unknown-linux-gnu | `mcount` | x| 1|
26
27On arm eabi targets, the mcount function is usually named `__gnu_mcount_nc`, though some targets may use different names. Implementers of counting function should consult the target specific documentation for quirks of each ABI function.
28
291. On x86-64, mcount and fentry must preserve the argument registers `rax`, `rcx`, `rdx`, `rsi`, `rdi`, `r8`, `r9`. When using fentry, the stack pointer `rsp` may need aligned to meet ABI requirements.
30
31## Implementing custom counting functions
32
33In essence, this is implementing the function `fn mcount(caller: *const std::ffi::c_void, callee: *const std::ffi::c_void)`. The calling convention for mcount follows its own ABI, which isn't usually the standard ABI for the target, but is enforced by preexisting convention.
34
35A trivial example on x86_64-unknown-linux-gnu looks something like the following. The `#[instrument_fn]` attribute can be used to disable profiling to simplify writing counting functions, but implementors must be very careful when calling other functions (or closures which fail to inline) as they may also call mcount.
36
37The following example can be compiled with `-Zinstrument-mcount=yes` or `-Zinstrument-mcount=fentry` on an x86_64-unknown-linux-gnu target. It is also acceptable to link objects with different usages of `-Zinstrument-mcount`, however doing so will require implementing both `__fentry__` and `mcount` on targets which support both.
38
39```rust
40#![feature(instrument_fn)]
41#![feature(abi_custom)]
42
43fn main() {
44 // Ensure all the early startup occurs before attempting to call this trivial, single-threaded
45 // counting function.
46 unsafe {
47 PROFILING_ENABLED = true;
48 }
49 println!("main() called");
50 unsafe {
51 PROFILING_ENABLED = false;
52 }
53}
54
55// This example is not threadsafe.
56pub static mut IN_MCOUNT: isize = 0;
57pub static mut PROFILING_ENABLED: bool = false;
58
59#[unsafe(no_mangle)]
60#[instrument_fn = "off"]
61unsafe extern "C" fn __count_fn(caller: u64, callee: u64) {
62 unsafe {
63 if IN_MCOUNT == 0 && PROFILING_ENABLED {
64 IN_MCOUNT += 1;
65 {
66 println!("mcount: call from 0x{caller:x} to 0x{callee:x}");
67 }
68 IN_MCOUNT -= 1;
69 }
70 }
71}
72
73// Define a custom mcount function. This may partially or fully override the glibc
74// implementation depending on linker options.
75#[unsafe(naked)]
76#[unsafe(no_mangle)]
77#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
78unsafe extern "custom" fn mcount() {
79 core::arch::naked_asm!(
80 // A simplified version based on the glibc x86-64 mcount wrapper.
81 // Save register arguments to the stack, and call the mcount above.
82 "push rax",
83 "push rcx",
84 "push rdx",
85 "push rsi",
86 "push rdi",
87 "push r8",
88 "push r9",
89 "mov rsi, 56[rsp]",
90 "mov rdi, 8[rbp]",
91 "call __count_fn",
92 "pop r9",
93 "pop r8",
94 "pop rdi",
95 "pop rsi",
96 "pop rdx",
97 "pop rcx",
98 "pop rax",
99 "ret",
100 )
101}
102
103// Supply a custom __fentry__ instead of glibc's. This has the same linker
104// restrictions as noted with mcount, but does not require a frame pointer.
105#[unsafe(naked)]
106#[unsafe(no_mangle)]
107#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
108unsafe extern "custom" fn __fentry__() {
109 core::arch::naked_asm!(
110 // __fentry__ is called before any other prologue actions, be careful
111 // with stack alignment. The stack slots look something like:
112 // [...]
113 // [caller return address]
114 // [callee return address] <- top of stack
115 "sub rsp, 8",
116 "push rax",
117 "push rcx",
118 "push rdx",
119 "push rsi",
120 "push rdi",
121 "push r8",
122 "push r9",
123 "mov rsi, 64[rsp]",
124 "mov rdi, 72[rsp]",
125 "call __count_fn",
126 "pop r9",
127 "pop r8",
128 "pop rdi",
129 "pop rsi",
130 "pop rdx",
131 "pop rcx",
132 "pop rax",
133 "add rsp, 8",
134 "ret",
135 )
136}
137```
138
139When run, the above program should produce output similar to:
140```txt
141mcount: call from 0x5614c97d778a to 0x5614c97d76e5
142main() called
143```
src/llvm-project+1-1
......@@ -1 +1 @@
1Subproject commit ec9ab9d68bf7a0e86b2ddf3c0e6e3c4620e02961
1Subproject commit 3c3f13025bf9f99bb2a757eb37dad4f09e7d6c36
tests/assembly-llvm/cmse-clear-padding.rs created+204
......@@ -0,0 +1,204 @@
1//@ add-minicore
2//@ min-llvm-version: 22
3//@ assembly-output: emit-asm
4//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
5//@ needs-llvm-components: arm
6#![crate_type = "lib"]
7#![feature(abi_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
8#![no_core]
9
10// Test that padding and other uninitialized bytes are zeroed when a value crosses the secure
11// boundary.
12//
13// The assembly uses the following instructions for clearing the bits:
14//
15// - `uxtb` clears bits 8..32
16// - `uxth` clears bits 16..32
17// - `bic` clears bits based on a mask
18//
19// When passing arguments the current implementation of the C ABI already clears padding sometimes,
20// but it's not something that can be relied on.
21
22extern crate minicore;
23use minicore::*;
24
25#[repr(C)]
26struct InnerPadding {
27 a: u8,
28 b: u16,
29}
30
31// CHECK-LABEL: c_ret_with_inner_padding:
32// CHECK: mov r7, sp
33// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
34#[no_mangle]
35extern "C" fn c_ret_with_inner_padding(a: u8, b: u16) -> InnerPadding {
36 InnerPadding { a, b }
37}
38
39// CHECK-LABEL: cmse_ret_with_inner_padding:
40// CHECK: mov r7, sp
41// CHECK-NEXT: uxtb r0, r0
42// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
43#[no_mangle]
44extern "cmse-nonsecure-entry" fn cmse_ret_with_inner_padding(a: u8, b: u16) -> InnerPadding {
45 InnerPadding { a, b }
46}
47
48// CHECK-LABEL: c_call_with_inner_padding:
49// CHECK: mov r7, sp
50// CHECK-NEXT: mov r2, r0
51// CHECK-NEXT: bic r0, r1, #65280
52// CHECK-NEXT: pop.w {r7, lr}
53#[no_mangle]
54extern "C" fn c_call_with_inner_padding(f: unsafe extern "C" fn(InnerPadding), x: InnerPadding) {
55 unsafe { f(x) }
56}
57
58// CHECK-LABEL: cmse_call_with_inner_padding:
59// CHECK: mov r7, sp
60// CHECK-NEXT: mov r2, r0
61// CHECK-NEXT: bic r0, r1, #65280
62// CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
63#[no_mangle]
64extern "C" fn cmse_call_with_inner_padding(
65 f: unsafe extern "cmse-nonsecure-call" fn(InnerPadding),
66 x: InnerPadding,
67) {
68 unsafe { f(x) }
69}
70
71#[repr(C)]
72struct TrailingPadding {
73 a: u16,
74 b: u8,
75}
76
77// CHECK-LABEL: c_ret_with_trailing_padding:
78// CHECK: mov r7, sp
79// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
80#[no_mangle]
81extern "C" fn c_ret_with_trailing_padding(a: u16, b: u8) -> TrailingPadding {
82 TrailingPadding { a, b }
83}
84
85// CHECK-LABEL: cmse_ret_with_trailing_padding:
86// CHECK: mov r7, sp
87// CHECK-NEXT: uxtb r1, r1
88// CHECK-NEXT: uxth r0, r0
89// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
90#[no_mangle]
91extern "cmse-nonsecure-entry" fn cmse_ret_with_trailing_padding(a: u16, b: u8) -> TrailingPadding {
92 TrailingPadding { a, b }
93}
94
95// CHECK-LABEL: c_call_with_trailing_padding:
96// CHECK: mov r7, sp
97// CHECK-NEXT: mov r2, r0
98// CHECK-NEXT: bic r0, r1, #-16777216
99// CHECK-NEXT: pop.w {r7, lr}
100#[no_mangle]
101extern "C" fn c_call_with_trailing_padding(
102 f: unsafe extern "C" fn(TrailingPadding),
103 x: TrailingPadding,
104) {
105 unsafe { f(x) }
106}
107
108// CHECK-LABEL: cmse_call_with_trailing_padding:
109// CHECK: mov r7, sp
110// CHECK-NEXT: mov r2, r0
111// CHECK-NEXT: bic r0, r1, #-16777216
112// CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
113#[no_mangle]
114extern "C" fn cmse_call_with_trailing_padding(
115 f: unsafe extern "cmse-nonsecure-call" fn(TrailingPadding),
116 x: TrailingPadding,
117) {
118 unsafe { f(x) }
119}
120
121#[repr(C, align(2))]
122struct WideU8 {
123 a: u8,
124}
125
126// CHECK-LABEL: c_ret_with_wide_u8:
127// CHECK: mov r7, sp
128// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
129#[no_mangle]
130extern "C" fn c_ret_with_wide_u8(a: u8, b: u8) -> [WideU8; 2] {
131 [WideU8 { a }, WideU8 { a: b }]
132}
133
134// CHECK-LABEL: cmse_ret_with_wide_u8:
135// CHECK: mov r7, sp
136// CHECK-NEXT: uxtb r1, r1
137// CHECK-NEXT: uxtb r0, r0
138// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
139#[no_mangle]
140extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8(a: u8, b: u8) -> [WideU8; 2] {
141 [WideU8 { a }, WideU8 { a: b }]
142}
143
144// CHECK-LABEL: c_call_with_inner_wide_u8:
145// CHECK: push {r7, lr}
146// CHECK-NEXT: .setfp r7, sp
147// CHECK-NEXT: mov r7, sp
148// CHECK-NEXT: mov lr, r3
149// CHECK-NEXT: mov r12, r0
150// CHECK-NEXT: ldr r3, [r7, #8]
151// CHECK-NEXT: mov r0, r1
152// CHECK-NEXT: mov r1, r2
153// CHECK-NEXT: mov r2, lr
154// CHECK-NEXT: pop.w {r7, lr}
155// CHECK-NEXT: bx r12
156#[no_mangle]
157extern "C" fn c_call_with_inner_wide_u8(f: unsafe extern "C" fn([WideU8; 8]), x: [WideU8; 8]) {
158 unsafe { f(x) }
159}
160
161// CHECK-LABEL: cmse_call_with_inner_wide_u8:
162// CHECK: push {r7, lr}
163// CHECK-NEXT: .setfp r7, sp
164// CHECK-NEXT: mov r7, sp
165// CHECK-NEXT: mov r12, r0
166// CHECK-NEXT: bic r0, r1, #-16711936
167// CHECK-NEXT: bic r1, r2, #-16711936
168// CHECK-NEXT: bic r2, r3, #-16711936
169// CHECK-NEXT: ldr r3, [r7, #8]
170// CHECK-NEXT: bic r3, r3, #-16711936
171// CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, r11}
172#[no_mangle]
173extern "C" fn cmse_call_with_inner_wide_u8(
174 f: unsafe extern "cmse-nonsecure-call" fn([WideU8; 8]),
175 x: [WideU8; 8],
176) {
177 unsafe { f(x) }
178}
179
180// CHECK-LABEL: cmse_ret_with_wide_u8_uninit:
181// CHECK: mov r7, sp
182// CHECK-NEXT: uxtb r0, r0
183// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
184// CHECK-NEXT: bic r0, r0, #-16711936
185#[no_mangle]
186extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit(
187 a: u16,
188 b: u16,
189) -> [MaybeUninit<WideU8>; 2] {
190 unsafe { [mem::transmute(a), mem::transmute(b)] }
191}
192
193// CHECK-LABEL: cmse_ret_with_wide_u8_uninit_tuple:
194// CHECK: mov r7, sp
195// CHECK-NEXT: uxtb r0, r0
196// CHECK-NEXT: orr.w r0, r0, r1, lsl #16
197// CHECK-NEXT: bic r0, r0, #-16711936
198#[no_mangle]
199extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit_tuple(
200 a: u16,
201 b: u16,
202) -> (MaybeUninit<WideU8>, MaybeUninit<WideU8>) {
203 unsafe { (mem::transmute(a), mem::transmute(b)) }
204}
tests/assembly-llvm/fentry.rs created+25
......@@ -0,0 +1,25 @@
1//@ assembly-output: emit-asm
2//@ compile-flags: -Zinstrument-mcount=fentry
3//@ add-minicore
4
5//@ revisions: X86 S390X
6//@[X86] compile-flags: --target=x86_64-unknown-linux-gnu -Cllvm-args=-x86-asm-syntax=intel
7//@[X86] needs-llvm-components: x86
8//@[S390X] compile-flags: --target=s390x-unknown-linux-gnu
9//@[S390X] needs-llvm-components: systemz
10
11#![crate_type = "lib"]
12#![feature(no_core)]
13#![no_core]
14
15extern crate minicore;
16
17// CHECK-LABEL: mcount_func:
18#[no_mangle]
19pub fn mcount_func(a: isize, b: isize) -> isize {
20 // X86: call __fentry__
21 // S390X: brasl %r0, __fentry__@PLT
22 a + b
23 // X86: ret
24 // S390X: br %r14
25}
tests/codegen-llvm/ilog_known_base.rs+4-4
......@@ -7,7 +7,7 @@
77// CHECK-LABEL: @checked_ilog2
88#[no_mangle]
99pub fn checked_ilog2(val: u32) -> Option<u32> {
10 // CHECK: %[[ICMP:.+]] = icmp ne i32 %val, 0
10 // CHECK: icmp {{ne|eq}} i32 %val, 0
1111 // CHECK: %[[CTZ:.+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %val, i1 true)
1212 // CHECK: %[[LOG2:.+]] = xor i32 %[[CTZ]], 31
1313 val.checked_ilog(2)
......@@ -17,7 +17,7 @@ pub fn checked_ilog2(val: u32) -> Option<u32> {
1717// CHECK-LABEL: @checked_ilog4
1818#[no_mangle]
1919pub fn checked_ilog4(val: u32) -> Option<u32> {
20 // CHECK: %[[ICMP:.+]] = icmp ne i32 %val, 0
20 // CHECK: icmp {{ne|eq}} i32 %val, 0
2121 // CHECK: %[[CTZ:.+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %val, i1 true)
2222 // CHECK: %[[DIV2:.+]] = lshr i32 %[[CTZ]], 1
2323 // CHECK: %[[LOG4:.+]] = xor i32 %[[DIV2]], 15
......@@ -28,9 +28,9 @@ pub fn checked_ilog4(val: u32) -> Option<u32> {
2828// CHECK-LABEL: @checked_ilog16
2929#[no_mangle]
3030pub fn checked_ilog16(val: u32) -> Option<u32> {
31 // CHECK: %[[ICMP:.+]] = icmp ne i32 %val, 0
31 // CHECK: icmp {{ne|eq}} i32 %val, 0
3232 // CHECK: %[[CTZ:.+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %val, i1 true)
3333 // CHECK: %[[DIV4:.+]] = lshr i32 %[[CTZ]], 2
34 // CHECK: %[[LOG16:.+]] = xor i32 %[[DIV2]], 7
34 // CHECK: %[[LOG16:.+]] = xor i32 %[[DIV4]], 7
3535 val.checked_ilog(16)
3636}
tests/codegen-llvm/instrument-fentry.rs created+25
......@@ -0,0 +1,25 @@
1//@ add-minicore
2//@ compile-flags: -Z instrument-mcount=fentry -Copt-level=0
3//
4//@ revisions: x86_64-linux
5//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
6//@[x86_64-linux] needs-llvm-components: x86
7//
8//@ revisions: x86-linux
9//@[x86-linux] compile-flags: --target=i686-unknown-linux-gnu
10//@[x86-linux] needs-llvm-components: x86
11//
12//@ revisions: s390x-linux
13//@[s390x-linux] compile-flags: --target=s390x-unknown-linux-gnu
14//@[s390x-linux] needs-llvm-components: systemz
15
16#![feature(no_core)]
17#![no_std]
18#![no_core]
19#![crate_type = "lib"]
20
21extern crate minicore;
22use minicore::*;
23
24// CHECK: attributes #{{.*}} "fentry-call"="true"
25pub fn foo() {}
tests/codegen-llvm/instrument_fn.rs+8-1
......@@ -1,10 +1,13 @@
11// Verify the #[instrument_fn] applies the correct LLVM IR function attributes.
22//
3//@ revisions:XRAY MCOUNT
3//@ revisions:XRAY MCOUNT FENTRY
44//@ add-minicore
55//@ compile-flags: -Copt-level=0
66//@ [XRAY] compile-flags: -Zinstrument-xray --target=x86_64-unknown-linux-gnu
77//@ [XRAY] needs-llvm-components: x86
8//@ [FENTRY] compile-flags: -Zinstrument-mcount=fentry -Copt-level=0
9//@ [FENTRY] compile-flags: --target=x86_64-unknown-linux-gnu
10//@ [FENTRY] needs-llvm-components: x86
811//@ [MCOUNT] compile-flags: -Zinstrument-mcount
912
1013#![feature(no_core)]
......@@ -27,12 +30,16 @@ fn instrument_off() {}
2730#[no_mangle]
2831#[instrument_fn = "on"]
2932// MCOUNT: define {{.*}}void @instrument_on() {{.*}} [[DFLT_ATTR]]
33// FENTRY: define void @instrument_on() {{.*}} [[DFLT_ATTR]]
3034// XRAY: define void @instrument_on() {{.*}} [[ON_ATTR:#[0-9]+]]
3135fn instrument_on() {}
3236
3337// MCOUNT: attributes [[DFLT_ATTR]] {{.*}} "instrument-function-entry-inlined"=
3438// MCOUNT-NOT: attributes [[OFF_ATTR]] {{.*}} "instrument-function-entry-inlined"=
3539
40// FENTRY: attributes [[DFLT_ATTR]] {{.*}} "fentry-call"="true"
41// FENTRY-NOT: attributes [[OFF_ATTR]] {{.*}} "fentry-call"="true"
42
3643// XRAY-NOT: attributes [[DFLT_ATTR]] {{.*}} "function-instrument"="xray-always"
3744// XRAY-NOT: attributes [[DFLT_ATTR]] {{.*}} "function-instrument"="xray-never"
3845// XRAY-NOT: attributes [[DFLT_ATTR]] {{.*}} "xray-skip-exit"
tests/codegen-llvm/issues/issue-107681-unwrap_unchecked.rs+5-5
......@@ -1,4 +1,6 @@
11//@ compile-flags: -Copt-level=3
2//@ filecheck-flags: --implicit-check-not 'br {{.*}}' --implicit-check-not 'select'
3//@ min-llvm-version: 22
24
35// Test for #107681.
46// Make sure we don't create `br` or `select` instructions.
......@@ -11,10 +13,8 @@ use std::slice::Iter;
1113#[no_mangle]
1214pub unsafe fn foo(x: &mut Copied<Iter<'_, u32>>) -> u32 {
1315 // CHECK-LABEL: @foo(
14 // CHECK-NOT: br {{.*}}
15 // CHECK-NOT: select
16 // CHECK: [[RET:%.*]] = load i32, ptr
17 // CHECK-NEXT: assume
18 // CHECK-NEXT: ret i32 [[RET]]
16 // CHECK: [[INNER:%.*]] = load ptr, ptr %x
17 // CHECK: [[RET:%.*]] = load i32, ptr [[INNER]]
18 // CHECK: ret i32 [[RET]]
1919 x.next().unwrap_unchecked()
2020}
tests/pretty/auxiliary/to-reuse-functions.rs deleted-14
......@@ -1,14 +0,0 @@
1//@ edition:2021
2
3#[must_use]
4#[cold]
5pub unsafe fn unsafe_fn_extern() -> usize { 1 }
6
7#[must_use = "extern_fn_extern: some reason"]
8#[deprecated]
9pub extern "C" fn extern_fn_extern() -> usize { 1 }
10
11pub const fn const_fn_extern() -> usize { 1 }
12
13#[must_use]
14pub async fn async_fn_extern() { }
tests/pretty/delegation-impl-reuse.pp deleted-45
......@@ -1,45 +0,0 @@
1#![feature(prelude_import)]
2#![no_std]
3//@ pretty-compare-only
4//@ pretty-mode:expanded
5//@ pp-exact:delegation-impl-reuse.pp
6
7#![allow(incomplete_features)]
8#![feature(fn_delegation)]
9extern crate std;
10#[prelude_import]
11use ::std::prelude::rust_2015::*;
12
13trait Trait<T> {
14 fn foo(&self) {}
15 fn bar(&self) {}
16 fn baz(&self) {}
17}
18
19struct S;
20
21impl Trait<{
22 struct S;
23 0
24 }> for S {
25 reuse Trait<{
26 struct S;
27 0
28 }>::foo {
29 self.0
30 }
31 reuse Trait<{
32 struct S;
33 0
34 }>::bar {
35 self.0
36 }
37 reuse Trait<{
38 struct S;
39 0
40 }>::baz {
41 self.0
42 }
43}
44
45fn main() {}
tests/pretty/delegation-impl-reuse.rs deleted-18
......@@ -1,18 +0,0 @@
1//@ pretty-compare-only
2//@ pretty-mode:expanded
3//@ pp-exact:delegation-impl-reuse.pp
4
5#![allow(incomplete_features)]
6#![feature(fn_delegation)]
7
8trait Trait<T> {
9 fn foo(&self) {}
10 fn bar(&self) {}
11 fn baz(&self) {}
12}
13
14struct S;
15
16reuse impl Trait<{ struct S; 0 }> for S { self.0 }
17
18fn main() {}
tests/pretty/delegation-inherit-attributes.pp deleted-124
......@@ -1,124 +0,0 @@
1//@ edition:2021
2//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
3//@ pretty-mode:hir
4//@ pretty-compare-only
5//@ pp-exact:delegation-inherit-attributes.pp
6
7#![allow(incomplete_features)]
8#![attr = Feature([fn_delegation#0])]
9extern crate std;
10#[attr = PreludeImport]
11use std::prelude::rust_2021::*;
12
13extern crate to_reuse_functions;
14
15mod to_reuse {
16 #[attr = MustUse {reason: "foo: some reason"}]
17 #[attr = Cold]
18 fn foo(x: usize) -> usize { x }
19
20 #[attr = MustUse]
21 #[attr = Cold]
22 fn foo_no_reason(x: usize) -> usize { x }
23
24 #[attr = Cold]
25 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
26 fn bar(x: usize) -> usize { x }
27}
28
29#[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
30#[attr = MustUse {reason: "foo: some reason"}]
31#[attr = Inline(Hint)]
32fn foo1(arg0: _) -> _ { to_reuse::foo(self + 1) }
33
34#[attr = MustUse]
35#[attr = Inline(Hint)]
36fn foo_no_reason(arg0: _) -> _ { to_reuse::foo_no_reason(self + 1) }
37
38#[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
39#[attr = MustUse {reason: "some reason"}]
40#[attr = Inline(Hint)]
41fn foo2(arg0: _) -> _ { to_reuse::foo(self + 1) }
42
43#[attr = Inline(Hint)]
44fn bar(arg0: _) -> _ { to_reuse::bar(arg0) }
45
46#[attr = MustUse]
47#[attr = Inline(Hint)]
48unsafe fn unsafe_fn_extern() -> _ { to_reuse_functions::unsafe_fn_extern() }
49#[attr = MustUse {reason: "extern_fn_extern: some reason"}]
50#[attr = Inline(Hint)]
51extern "C" fn extern_fn_extern()
52 -> _ { to_reuse_functions::extern_fn_extern() }
53#[attr = Inline(Hint)]
54const fn const_fn_extern() -> _ { to_reuse_functions::const_fn_extern() }
55#[attr = MustUse {reason: "some reason"}]
56#[attr = Inline(Hint)]
57async fn async_fn_extern() -> _ { to_reuse_functions::async_fn_extern() }
58
59mod recursive {
60 // Check that `baz` inherit attribute from `foo`
61 mod first {
62 fn bar() { }
63 #[attr = MustUse {reason: "some reason"}]
64 #[attr = Inline(Hint)]
65 fn foo() -> _ { bar() }
66 #[attr = MustUse {reason: "some reason"}]
67 #[attr = Inline(Hint)]
68 fn baz() -> _ { foo() }
69 }
70
71 // Check that `baz` inherit attribute from `bar`
72 mod second {
73 #[attr = MustUse {reason: "some reason"}]
74 fn bar() { }
75
76 #[attr = MustUse {reason: "some reason"}]
77 #[attr = Inline(Hint)]
78 fn foo() -> _ { bar() }
79 #[attr = MustUse {reason: "some reason"}]
80 #[attr = Inline(Hint)]
81 fn baz() -> _ { foo() }
82 }
83
84 // Check that `foo5` don't inherit attribute from `bar`
85 // and inherit attribute from foo4, check that foo1, foo2 and foo3
86 // inherit attribute from bar
87 mod third {
88 #[attr = MustUse {reason: "some reason"}]
89 fn bar() { }
90 #[attr = MustUse {reason: "some reason"}]
91 #[attr = Inline(Hint)]
92 fn foo1() -> _ { bar() }
93 #[attr = MustUse {reason: "some reason"}]
94 #[attr = Inline(Hint)]
95 fn foo2() -> _ { foo1() }
96 #[attr = MustUse {reason: "some reason"}]
97 #[attr = Inline(Hint)]
98 fn foo3() -> _ { foo2() }
99 #[attr = MustUse {reason: "foo4"}]
100 #[attr = Inline(Hint)]
101 fn foo4() -> _ { foo3() }
102 #[attr = MustUse {reason: "foo4"}]
103 #[attr = Inline(Hint)]
104 fn foo5() -> _ { foo4() }
105 }
106
107 mod fourth {
108 trait T {
109 fn foo(&self, x: usize) -> usize { x + 1 }
110 }
111
112 struct X;
113 impl T for X { }
114
115 #[attr = MustUse {reason: "some reason"}]
116 #[attr = Inline(Hint)]
117 fn foo(self: _, arg1: _) -> _ { <X as T>::foo(self + 1, arg1) }
118 #[attr = MustUse {reason: "some reason"}]
119 #[attr = Inline(Hint)]
120 fn bar(arg0: _, arg1: _) -> _ { foo(self + 1, arg1) }
121 }
122}
123
124fn main() { }
tests/pretty/delegation-inherit-attributes.rs deleted-101
......@@ -1,101 +0,0 @@
1//@ edition:2021
2//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
3//@ pretty-mode:hir
4//@ pretty-compare-only
5//@ pp-exact:delegation-inherit-attributes.pp
6
7#![allow(incomplete_features)]
8#![feature(fn_delegation)]
9
10extern crate to_reuse_functions;
11
12mod to_reuse {
13 #[must_use = "foo: some reason"]
14 #[cold]
15 pub fn foo(x: usize) -> usize {
16 x
17 }
18
19 #[must_use]
20 #[cold]
21 pub fn foo_no_reason(x: usize) -> usize {
22 x
23 }
24
25 #[cold]
26 #[deprecated]
27 pub fn bar(x: usize) -> usize {
28 x
29 }
30}
31
32#[deprecated]
33reuse to_reuse::foo as foo1 {
34 self + 1
35}
36
37reuse to_reuse::foo_no_reason {
38 self + 1
39}
40
41#[deprecated]
42#[must_use = "some reason"]
43reuse to_reuse::foo as foo2 {
44 self + 1
45}
46
47reuse to_reuse::bar;
48
49reuse to_reuse_functions::unsafe_fn_extern;
50reuse to_reuse_functions::extern_fn_extern;
51reuse to_reuse_functions::const_fn_extern;
52#[must_use = "some reason"]
53reuse to_reuse_functions::async_fn_extern;
54
55mod recursive {
56 // Check that `baz` inherit attribute from `foo`
57 mod first {
58 fn bar() {}
59 #[must_use = "some reason"]
60 reuse bar as foo;
61 reuse foo as baz;
62 }
63
64 // Check that `baz` inherit attribute from `bar`
65 mod second {
66 #[must_use = "some reason"]
67 fn bar() {}
68
69 reuse bar as foo;
70 reuse foo as baz;
71 }
72
73 // Check that `foo5` don't inherit attribute from `bar`
74 // and inherit attribute from foo4, check that foo1, foo2 and foo3
75 // inherit attribute from bar
76 mod third {
77 #[must_use = "some reason"]
78 fn bar() {}
79 reuse bar as foo1;
80 reuse foo1 as foo2;
81 reuse foo2 as foo3;
82 #[must_use = "foo4"]
83 reuse foo3 as foo4;
84 reuse foo4 as foo5;
85 }
86
87 mod fourth {
88 trait T {
89 fn foo(&self, x: usize) -> usize { x + 1 }
90 }
91
92 struct X;
93 impl T for X {}
94
95 #[must_use = "some reason"]
96 reuse <X as T>::foo { self + 1 }
97 reuse foo as bar { self + 1 }
98 }
99}
100
101fn main() {}
tests/pretty/delegation-inline-attribute.pp deleted-92
......@@ -1,92 +0,0 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:delegation-inline-attribute.pp
4
5#![allow(incomplete_features)]
6#![attr = Feature([fn_delegation#0])]
7extern crate std;
8#[attr = PreludeImport]
9use ::std::prelude::rust_2015::*;
10
11mod to_reuse {
12 fn foo(x: usize) -> usize { x }
13}
14
15// Check that #[inline(hint)] is added to foo reuse
16#[attr = Inline(Hint)]
17fn bar(arg0: _) -> _ { to_reuse::foo(self + 1) }
18
19trait Trait {
20 fn foo(&self) { }
21 fn foo1(&self) { }
22 fn foo2(&self) { }
23 fn foo3(&self) { }
24 fn foo4(&self) { }
25}
26
27impl Trait for u8 { }
28
29struct S(u8);
30
31mod to_import {
32 fn check(arg: &'_ u8) -> &'_ u8 { arg }
33}
34
35impl Trait for S {
36 // Check that #[inline(hint)] is added to foo reuse
37 #[attr = Inline(Hint)]
38 fn foo(self: _)
39 ->
40 _ {
41 // Check that #[inline(hint)] is added to foo0 reuse inside another reuse
42 #[attr = Inline(Hint)]
43 fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }
44
45 // Check that #[inline(hint)] is added when other attributes present in inner reuse
46 #[attr = Cold]
47 #[attr = MustUse]
48 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
49 #[attr = Inline(Hint)]
50 fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }
51
52 // Check that #[inline(never)] is preserved in inner reuse
53 #[attr = Inline(Never)]
54 fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) }
55
56 // Check that #[inline(always)] is preserved in inner reuse
57 #[attr = Inline(Always)]
58 fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }
59
60 // Check that #[inline(never)] is preserved when there are other attributes in inner reuse
61 #[attr = Cold]
62 #[attr = MustUse]
63 #[attr = Inline(Never)]
64 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
65 fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
66 Trait::foo(self)
67 }
68
69 // Check that #[inline(hint)] is added when there are other attributes present in trait reuse
70 #[attr = Cold]
71 #[attr = MustUse]
72 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
73 #[attr = Inline(Hint)]
74 fn foo1(self: _) -> _ { Trait::foo1(self.0) }
75
76 // Check that #[inline(never)] is preserved in trait reuse
77 #[attr = Inline(Never)]
78 fn foo2(self: _) -> _ { Trait::foo2(self.0) }
79
80 // Check that #[inline(always)] is preserved in trait reuse
81 #[attr = Inline(Always)]
82 fn foo3(self: _) -> _ { Trait::foo3(self.0) }
83
84 // Check that #[inline(never)] is preserved when there are other attributes in trait reuse
85 #[attr = Cold]
86 #[attr = MustUse]
87 #[attr = Inline(Never)]
88 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
89 fn foo4(self: _) -> _ { Trait::foo4(self.0) }
90}
91
92fn main() { }
tests/pretty/delegation-inline-attribute.rs deleted-104
......@@ -1,104 +0,0 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:delegation-inline-attribute.pp
4
5#![allow(incomplete_features)]
6#![feature(fn_delegation)]
7
8mod to_reuse {
9 pub fn foo(x: usize) -> usize {
10 x
11 }
12}
13
14// Check that #[inline(hint)] is added to foo reuse
15reuse to_reuse::foo as bar {
16 self + 1
17}
18
19trait Trait {
20 fn foo(&self) {}
21 fn foo1(&self) {}
22 fn foo2(&self) {}
23 fn foo3(&self) {}
24 fn foo4(&self) {}
25}
26
27impl Trait for u8 {}
28
29struct S(u8);
30
31mod to_import {
32 pub fn check(arg: &u8) -> &u8 { arg }
33}
34
35impl Trait for S {
36 // Check that #[inline(hint)] is added to foo reuse
37 reuse Trait::foo {
38 // Check that #[inline(hint)] is added to foo0 reuse inside another reuse
39 reuse to_reuse::foo as foo0 {
40 self + 1
41 }
42
43 // Check that #[inline(hint)] is added when other attributes present in inner reuse
44 #[cold]
45 #[must_use]
46 #[deprecated]
47 reuse to_reuse::foo as foo1 {
48 self / 2
49 }
50
51 // Check that #[inline(never)] is preserved in inner reuse
52 #[inline(never)]
53 reuse to_reuse::foo as foo2 {
54 self / 2
55 }
56
57 // Check that #[inline(always)] is preserved in inner reuse
58 #[inline(always)]
59 reuse to_reuse::foo as foo3 {
60 self / 2
61 }
62
63 // Check that #[inline(never)] is preserved when there are other attributes in inner reuse
64 #[cold]
65 #[must_use]
66 #[inline(never)]
67 #[deprecated]
68 reuse to_reuse::foo as foo4 {
69 self / 2
70 }
71 }
72
73 // Check that #[inline(hint)] is added when there are other attributes present in trait reuse
74 #[cold]
75 #[must_use]
76 #[deprecated]
77 reuse Trait::foo1 {
78 self.0
79 }
80
81 // Check that #[inline(never)] is preserved in trait reuse
82 #[inline(never)]
83 reuse Trait::foo2 {
84 self.0
85 }
86
87 // Check that #[inline(always)] is preserved in trait reuse
88 #[inline(always)]
89 reuse Trait::foo3 {
90 self.0
91 }
92
93 // Check that #[inline(never)] is preserved when there are other attributes in trait reuse
94 #[cold]
95 #[must_use]
96 #[inline(never)]
97 #[deprecated]
98 reuse Trait::foo4 {
99 self.0
100 }
101}
102
103fn main() {
104}
tests/pretty/delegation-self-rename.pp deleted-58
......@@ -1,58 +0,0 @@
1#![attr = Feature([fn_delegation#0])]
2extern crate std;
3#[attr = PreludeImport]
4use ::std::prelude::rust_2015::*;
5//@ pretty-compare-only
6//@ pretty-mode:hir
7//@ pp-exact:delegation-self-rename.pp
8
9
10trait Trait<'a, A, const B: bool> {
11 fn foo<'b, const B2: bool, T, U,
12 impl FnOnce() -> usize>(&self, f: impl FnOnce() -> usize) -> usize
13 where impl FnOnce() -> usize: FnOnce() -> usize { f() + 1 }
14}
15
16struct X;
17impl <'a, A, const B: bool> Trait<'a, A, B> for X { }
18
19#[attr = Inline(Hint)]
20fn foo<'a, Self, A, const B: _, const B2: _, T, U,
21 impl FnOnce() -> usize>(self: _, arg1: _) -> _ where
22 'a:'a { <Self as Trait::<'a, A, B>>::foo::<B2, T, U>(self, arg1) }
23#[attr = Inline(Hint)]
24fn bar<Self, impl FnOnce() -> usize>(self: _, arg1: _)
25 ->
26 _ {
27 <Self as Trait::<'static, (), true>>::foo::<true, (), ()>(self, arg1)
28}
29
30#[attr = Inline(Hint)]
31fn foo2<'a, This, A, const B: _, const B2: _, T, U,
32 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
33 'a:'a { foo::<'a, This, A, B, B2, T, U>(arg0, arg1) }
34#[attr = Inline(Hint)]
35fn bar2<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
36 -> _ { bar::<This>(arg0, arg1) }
37
38trait Trait2 {
39 #[attr = Inline(Hint)]
40 fn foo3<'a, This, A, const B: _, const B2: _, T, U,
41 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
42 'a:'a { foo2::<'a, This, A, B, B2, T, U>(arg0, arg1) }
43 #[attr = Inline(Hint)]
44 fn bar3<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
45 -> _ { bar2::<This>(arg0, arg1) }
46}
47
48impl Trait2 for () { }
49
50#[attr = Inline(Hint)]
51fn foo4<'a, This, A, const B: _, const B2: _, T, U,
52 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
53 'a:'a { <() as Trait2>::foo3::<'a, This, A, B, B2, T, U>(arg0, arg1) }
54#[attr = Inline(Hint)]
55fn bar4<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
56 -> _ { <() as Trait2>::bar3::<This>(arg0, arg1) }
57
58fn main() { }
tests/pretty/delegation-self-rename.rs deleted-32
......@@ -1,32 +0,0 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:delegation-self-rename.pp
4
5#![feature(fn_delegation)]
6
7trait Trait<'a, A, const B: bool> {
8 fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
9 f() + 1
10 }
11}
12
13struct X;
14impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
15
16reuse Trait::foo;
17reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
18
19reuse foo as foo2;
20reuse bar as bar2;
21
22trait Trait2 {
23 reuse foo2 as foo3;
24 reuse bar2 as bar3;
25}
26
27impl Trait2 for () {}
28
29reuse <() as Trait2>::foo3 as foo4;
30reuse <() as Trait2>::bar3 as bar4;
31
32fn main() {}
tests/pretty/delegation.rs deleted-25
......@@ -1,25 +0,0 @@
1#![feature(fn_delegation)]
2//~^ WARN the feature `fn_delegation` is incomplete
3
4//@ pp-exact
5
6trait Trait {
7 fn bar(&self, x: i32) -> i32 { x }
8}
9
10struct F;
11impl Trait for F {}
12
13struct S(F);
14impl Trait for S {
15 reuse Trait::bar { &self.0 }
16}
17
18mod to_reuse {
19 pub fn foo() {}
20}
21
22#[inline]
23pub reuse to_reuse::foo;
24
25fn main() {}
tests/pretty/delegation/auxiliary/to-reuse-functions.rs created+14
......@@ -0,0 +1,14 @@
1//@ edition:2021
2
3#[must_use]
4#[cold]
5pub unsafe fn unsafe_fn_extern() -> usize { 1 }
6
7#[must_use = "extern_fn_extern: some reason"]
8#[deprecated]
9pub extern "C" fn extern_fn_extern() -> usize { 1 }
10
11pub const fn const_fn_extern() -> usize { 1 }
12
13#[must_use]
14pub async fn async_fn_extern() { }
tests/pretty/delegation/delegation.rs created+25
......@@ -0,0 +1,25 @@
1#![feature(fn_delegation)]
2//~^ WARN the feature `fn_delegation` is incomplete
3
4//@ pp-exact
5
6trait Trait {
7 fn bar(&self, x: i32) -> i32 { x }
8}
9
10struct F;
11impl Trait for F {}
12
13struct S(F);
14impl Trait for S {
15 reuse Trait::bar { &self.0 }
16}
17
18mod to_reuse {
19 pub fn foo() {}
20}
21
22#[inline]
23pub reuse to_reuse::foo;
24
25fn main() {}
tests/pretty/delegation/generics.pp created+131
......@@ -0,0 +1,131 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:generics.pp
4
5#![allow(incomplete_features)]
6#![attr = Feature([fn_delegation#0])]
7extern crate std;
8#[attr = PreludeImport]
9use ::std::prelude::rust_2015::*;
10
11mod free_to_trait {
12 trait Trait<'a, XX, Y, T = (), const N: usize = 2> {
13 fn method<A, B>(&self, t: (T, A, B), slice: &'_ [usize; N]) { }
14 fn r#static<A, B>(t: (T, A, B), slice: &'_ [usize; N]) { }
15 }
16
17 struct X;
18 impl <XX, Y, T, const N: usize> Trait<'_, XX, Y, T, N> for X { }
19
20 // When infer is specified for default parameter the generic param is generated.
21 #[attr = Inline(Hint)]
22 fn foo<'a, Self, XX, Y, T, const N: _, A, B>(self: _, arg1: _, arg2: _)
23 -> _ where
24 'a:'a {
25 <Self as Trait::<'a, XX, Y, T, N>>::method::<A, B>(self, arg1, arg2)
26 }
27 #[attr = Inline(Hint)]
28 fn static_foo<'a, Self, XX, Y, T, const N: _, A, B>(arg0: _, arg1: _) -> _
29 where
30 'a:'a {
31 <Self as Trait::<'a, XX, Y, T, N>>::r#static::<A, B>(arg0, arg1)
32 }
33
34 // When default params are omitted they are not generated but used in signature inheritance.
35 #[attr = Inline(Hint)]
36 fn bar<'a, Self, XX, Y, A, B>(self: _, arg1: _, arg2: _) -> _ where
37 'a:'a {
38 <Self as Trait::<'a, XX, Y>>::method::<A, B>(self, arg1, arg2)
39 }
40 #[attr = Inline(Hint)]
41 fn static_bar<'a, Self, XX, Y, A, B>(arg0: _, arg1: _) -> _ where
42 'a:'a { <Self as Trait::<'a, XX, Y>>::r#static::<A, B>(arg0, arg1) }
43
44 // Check with user specified args in child:
45 // When infer is specified for default parameter the generic param is generated.
46 #[attr = Inline(Hint)]
47 fn foo1<'a, Self, XX, Y, T, const N: _, B>(self: _, arg1: _, arg2: _) -> _
48 where
49 'a:'a {
50 <Self as Trait::<'a, XX, Y, T, N>>::method::<(), B>(self, arg1, arg2)
51 }
52 #[attr = Inline(Hint)]
53 fn static_foo1<'a, Self, XX, Y, T, const N: _, B>(arg0: _, arg1: _) -> _
54 where
55 'a:'a {
56 <Self as Trait::<'a, XX, Y, T, N>>::r#static::<(), B>(arg0, arg1)
57 }
58
59 // When default params are omitted they are not generated but used in signature inheritance.
60 #[attr = Inline(Hint)]
61 fn bar1<'a, Self, XX, Y, A>(self: _, arg1: _, arg2: _) -> _ where
62 'a:'a {
63 <Self as Trait::<'a, XX, Y>>::method::<A, ()>(self, arg1, arg2)
64 }
65 #[attr = Inline(Hint)]
66 fn static_bar1<'a, Self, XX, Y, A>(arg0: _, arg1: _) -> _ where
67 'a:'a { <Self as Trait::<'a, XX, Y>>::r#static::<A, ()>(arg0, arg1) }
68
69 // Check with explicit self type.
70 #[attr = Inline(Hint)]
71 fn foo2<'a, XX, Y, T, const N: _, A, B>(self: _, arg1: _, arg2: _) -> _
72 where
73 'a:'a {
74 <X as Trait::<'a, XX, Y, T, N>>::method::<A, B>(self, arg1, arg2)
75 }
76 #[attr = Inline(Hint)]
77 fn static_foo2<'a, XX, Y, T, const N: _, A, B>(arg0: _, arg1: _) -> _
78 where
79 'a:'a {
80 <X as Trait::<'a, XX, Y, T, N>>::r#static::<A, B>(arg0, arg1)
81 }
82
83 #[attr = Inline(Hint)]
84 fn bar2<'a, XX, Y, A, B>(self: _, arg1: _, arg2: _) -> _ where
85 'a:'a { <X as Trait::<'a, XX, Y>>::method::<A, B>(self, arg1, arg2) }
86 #[attr = Inline(Hint)]
87 fn static_bar2<'a, XX, Y, A, B>(arg0: _, arg1: _) -> _ where
88 'a:'a { <X as Trait::<'a, XX, Y>>::r#static::<A, B>(arg0, arg1) }
89
90 #[attr = Inline(Hint)]
91 fn foo3<'a, XX, Y, T, const N: _, B>(self: _, arg1: _, arg2: _) -> _ where
92 'a:'a {
93 <X as Trait::<'a, XX, Y, T, N>>::method::<(), B>(self, arg1, arg2)
94 }
95 #[attr = Inline(Hint)]
96 fn static_foo3<'a, XX, Y, T, const N: _, B>(arg0: _, arg1: _) -> _ where
97 'a:'a {
98 <X as Trait::<'a, XX, Y, T, N>>::r#static::<(), B>(arg0, arg1)
99 }
100
101 #[attr = Inline(Hint)]
102 fn bar3<'a, XX, Y, A>(self: _, arg1: _, arg2: _) -> _ where
103 'a:'a { <X as Trait::<'a, XX, Y>>::method::<A, ()>(self, arg1, arg2) }
104 #[attr = Inline(Hint)]
105 fn static_bar3<'a, XX, Y, A>(arg0: _, arg1: _) -> _ where
106 'a:'a { <X as Trait::<'a, XX, Y>>::r#static::<A, ()>(arg0, arg1) }
107}
108
109mod trait_impl_to_trait {
110 trait Trait<'a, X, Y, T = (), const N: usize = 2> {
111 fn foo(&self, t: (T, T, T), slice: &'_ [usize; N]) { }
112 fn bar(&self, t: (T, T, T), slice: &'_ [usize; N]) { }
113 }
114
115 struct S;
116 impl <X, Y> Trait<'_, X, Y> for S { }
117
118 struct W(S);
119 impl <X, Y> Trait<'_, X, Y> for W {
120 // Generics of both methods match generics of their signature
121 // functions in `Trait` declaration, no matter specified infers.
122 #[attr = Inline(Hint)]
123 fn foo(self: _, arg1: _, arg2: _)
124 -> _ { Trait::<'static, X, Y>::foo(self.0, arg1, arg2) }
125 #[attr = Inline(Hint)]
126 fn bar(self: _, arg1: _, arg2: _)
127 -> _ { Trait::<'static, X, Y, _, _>::foo(self.0, arg1, arg2) }
128 }
129}
130
131fn main() { }
tests/pretty/delegation/generics.rs created+66
......@@ -0,0 +1,66 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:generics.pp
4
5#![allow(incomplete_features)]
6#![feature(fn_delegation)]
7
8mod free_to_trait {
9 trait Trait<'a, XX, Y, T = (), const N: usize = 2> {
10 fn method<A, B>(&self, t: (T, A, B), slice: &[usize; N]) {}
11 fn r#static<A, B>(t: (T, A, B), slice: &[usize; N]) {}
12 }
13
14 struct X;
15 impl<XX, Y, T, const N: usize> Trait<'_, XX, Y, T, N> for X {}
16
17 // When infer is specified for default parameter the generic param is generated.
18 reuse Trait::<'_, _, _, _, _>::method as foo;
19 reuse Trait::<'_, _, _, _, _>::r#static as static_foo;
20
21 // When default params are omitted they are not generated but used in signature inheritance.
22 reuse Trait::<'_, _, _>::method as bar;
23 reuse Trait::<'_, _, _>::r#static as static_bar;
24
25 // Check with user specified args in child:
26 // When infer is specified for default parameter the generic param is generated.
27 reuse Trait::<'_, _, _, _, _>::method::<(), _> as foo1;
28 reuse Trait::<'_, _, _, _, _>::r#static::<(), _> as static_foo1;
29
30 // When default params are omitted they are not generated but used in signature inheritance.
31 reuse Trait::<'_, _, _>::method::<_, ()> as bar1;
32 reuse Trait::<'_, _, _>::r#static::<_, ()> as static_bar1;
33
34 // Check with explicit self type.
35 reuse <X as Trait::<'_, _, _, _, _>>::method as foo2;
36 reuse <X as Trait::<'_, _, _, _, _>>::r#static as static_foo2;
37
38 reuse <X as Trait::<'_, _, _>>::method as bar2;
39 reuse <X as Trait::<'_, _, _>>::r#static as static_bar2;
40
41 reuse <X as Trait::<'_, _, _, _, _>>::method::<(), _> as foo3;
42 reuse <X as Trait::<'_, _, _, _, _>>::r#static::<(), _> as static_foo3;
43
44 reuse <X as Trait::<'_, _, _>>::method::<_, ()> as bar3;
45 reuse <X as Trait::<'_, _, _>>::r#static::<_, ()> as static_bar3;
46}
47
48mod trait_impl_to_trait {
49 trait Trait<'a, X, Y, T = (), const N: usize = 2> {
50 fn foo(&self, t: (T, T, T), slice: &[usize; N]) {}
51 fn bar(&self, t: (T, T, T), slice: &[usize; N]) {}
52 }
53
54 struct S;
55 impl<X, Y> Trait<'_, X, Y> for S {}
56
57 struct W(S);
58 impl<X, Y> Trait<'_, X, Y> for W {
59 // Generics of both methods match generics of their signature
60 // functions in `Trait` declaration, no matter specified infers.
61 reuse Trait::<'static, X, Y>::foo { self.0 }
62 reuse Trait::<'static, X, Y, _, _>::foo as bar { self.0 }
63 }
64}
65
66fn main() {}
tests/pretty/delegation/impl-reuse.pp created+45
......@@ -0,0 +1,45 @@
1#![feature(prelude_import)]
2#![no_std]
3//@ pretty-compare-only
4//@ pretty-mode:expanded
5//@ pp-exact:impl-reuse.pp
6
7#![allow(incomplete_features)]
8#![feature(fn_delegation)]
9extern crate std;
10#[prelude_import]
11use ::std::prelude::rust_2015::*;
12
13trait Trait<T> {
14 fn foo(&self) {}
15 fn bar(&self) {}
16 fn baz(&self) {}
17}
18
19struct S;
20
21impl Trait<{
22 struct S;
23 0
24 }> for S {
25 reuse Trait<{
26 struct S;
27 0
28 }>::foo {
29 self.0
30 }
31 reuse Trait<{
32 struct S;
33 0
34 }>::bar {
35 self.0
36 }
37 reuse Trait<{
38 struct S;
39 0
40 }>::baz {
41 self.0
42 }
43}
44
45fn main() {}
tests/pretty/delegation/impl-reuse.rs created+18
......@@ -0,0 +1,18 @@
1//@ pretty-compare-only
2//@ pretty-mode:expanded
3//@ pp-exact:impl-reuse.pp
4
5#![allow(incomplete_features)]
6#![feature(fn_delegation)]
7
8trait Trait<T> {
9 fn foo(&self) {}
10 fn bar(&self) {}
11 fn baz(&self) {}
12}
13
14struct S;
15
16reuse impl Trait<{ struct S; 0 }> for S { self.0 }
17
18fn main() {}
tests/pretty/delegation/inherit-attributes.pp created+124
......@@ -0,0 +1,124 @@
1//@ edition:2021
2//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
3//@ pretty-mode:hir
4//@ pretty-compare-only
5//@ pp-exact:inherit-attributes.pp
6
7#![allow(incomplete_features)]
8#![attr = Feature([fn_delegation#0])]
9extern crate std;
10#[attr = PreludeImport]
11use std::prelude::rust_2021::*;
12
13extern crate to_reuse_functions;
14
15mod to_reuse {
16 #[attr = MustUse {reason: "foo: some reason"}]
17 #[attr = Cold]
18 fn foo(x: usize) -> usize { x }
19
20 #[attr = MustUse]
21 #[attr = Cold]
22 fn foo_no_reason(x: usize) -> usize { x }
23
24 #[attr = Cold]
25 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
26 fn bar(x: usize) -> usize { x }
27}
28
29#[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
30#[attr = MustUse {reason: "foo: some reason"}]
31#[attr = Inline(Hint)]
32fn foo1(arg0: _) -> _ { to_reuse::foo(self + 1) }
33
34#[attr = MustUse]
35#[attr = Inline(Hint)]
36fn foo_no_reason(arg0: _) -> _ { to_reuse::foo_no_reason(self + 1) }
37
38#[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
39#[attr = MustUse {reason: "some reason"}]
40#[attr = Inline(Hint)]
41fn foo2(arg0: _) -> _ { to_reuse::foo(self + 1) }
42
43#[attr = Inline(Hint)]
44fn bar(arg0: _) -> _ { to_reuse::bar(arg0) }
45
46#[attr = MustUse]
47#[attr = Inline(Hint)]
48unsafe fn unsafe_fn_extern() -> _ { to_reuse_functions::unsafe_fn_extern() }
49#[attr = MustUse {reason: "extern_fn_extern: some reason"}]
50#[attr = Inline(Hint)]
51extern "C" fn extern_fn_extern()
52 -> _ { to_reuse_functions::extern_fn_extern() }
53#[attr = Inline(Hint)]
54const fn const_fn_extern() -> _ { to_reuse_functions::const_fn_extern() }
55#[attr = MustUse {reason: "some reason"}]
56#[attr = Inline(Hint)]
57async fn async_fn_extern() -> _ { to_reuse_functions::async_fn_extern() }
58
59mod recursive {
60 // Check that `baz` inherit attribute from `foo`
61 mod first {
62 fn bar() { }
63 #[attr = MustUse {reason: "some reason"}]
64 #[attr = Inline(Hint)]
65 fn foo() -> _ { bar() }
66 #[attr = MustUse {reason: "some reason"}]
67 #[attr = Inline(Hint)]
68 fn baz() -> _ { foo() }
69 }
70
71 // Check that `baz` inherit attribute from `bar`
72 mod second {
73 #[attr = MustUse {reason: "some reason"}]
74 fn bar() { }
75
76 #[attr = MustUse {reason: "some reason"}]
77 #[attr = Inline(Hint)]
78 fn foo() -> _ { bar() }
79 #[attr = MustUse {reason: "some reason"}]
80 #[attr = Inline(Hint)]
81 fn baz() -> _ { foo() }
82 }
83
84 // Check that `foo5` don't inherit attribute from `bar`
85 // and inherit attribute from foo4, check that foo1, foo2 and foo3
86 // inherit attribute from bar
87 mod third {
88 #[attr = MustUse {reason: "some reason"}]
89 fn bar() { }
90 #[attr = MustUse {reason: "some reason"}]
91 #[attr = Inline(Hint)]
92 fn foo1() -> _ { bar() }
93 #[attr = MustUse {reason: "some reason"}]
94 #[attr = Inline(Hint)]
95 fn foo2() -> _ { foo1() }
96 #[attr = MustUse {reason: "some reason"}]
97 #[attr = Inline(Hint)]
98 fn foo3() -> _ { foo2() }
99 #[attr = MustUse {reason: "foo4"}]
100 #[attr = Inline(Hint)]
101 fn foo4() -> _ { foo3() }
102 #[attr = MustUse {reason: "foo4"}]
103 #[attr = Inline(Hint)]
104 fn foo5() -> _ { foo4() }
105 }
106
107 mod fourth {
108 trait T {
109 fn foo(&self, x: usize) -> usize { x + 1 }
110 }
111
112 struct X;
113 impl T for X { }
114
115 #[attr = MustUse {reason: "some reason"}]
116 #[attr = Inline(Hint)]
117 fn foo(self: _, arg1: _) -> _ { <X as T>::foo(self + 1, arg1) }
118 #[attr = MustUse {reason: "some reason"}]
119 #[attr = Inline(Hint)]
120 fn bar(arg0: _, arg1: _) -> _ { foo(self + 1, arg1) }
121 }
122}
123
124fn main() { }
tests/pretty/delegation/inherit-attributes.rs created+101
......@@ -0,0 +1,101 @@
1//@ edition:2021
2//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
3//@ pretty-mode:hir
4//@ pretty-compare-only
5//@ pp-exact:inherit-attributes.pp
6
7#![allow(incomplete_features)]
8#![feature(fn_delegation)]
9
10extern crate to_reuse_functions;
11
12mod to_reuse {
13 #[must_use = "foo: some reason"]
14 #[cold]
15 pub fn foo(x: usize) -> usize {
16 x
17 }
18
19 #[must_use]
20 #[cold]
21 pub fn foo_no_reason(x: usize) -> usize {
22 x
23 }
24
25 #[cold]
26 #[deprecated]
27 pub fn bar(x: usize) -> usize {
28 x
29 }
30}
31
32#[deprecated]
33reuse to_reuse::foo as foo1 {
34 self + 1
35}
36
37reuse to_reuse::foo_no_reason {
38 self + 1
39}
40
41#[deprecated]
42#[must_use = "some reason"]
43reuse to_reuse::foo as foo2 {
44 self + 1
45}
46
47reuse to_reuse::bar;
48
49reuse to_reuse_functions::unsafe_fn_extern;
50reuse to_reuse_functions::extern_fn_extern;
51reuse to_reuse_functions::const_fn_extern;
52#[must_use = "some reason"]
53reuse to_reuse_functions::async_fn_extern;
54
55mod recursive {
56 // Check that `baz` inherit attribute from `foo`
57 mod first {
58 fn bar() {}
59 #[must_use = "some reason"]
60 reuse bar as foo;
61 reuse foo as baz;
62 }
63
64 // Check that `baz` inherit attribute from `bar`
65 mod second {
66 #[must_use = "some reason"]
67 fn bar() {}
68
69 reuse bar as foo;
70 reuse foo as baz;
71 }
72
73 // Check that `foo5` don't inherit attribute from `bar`
74 // and inherit attribute from foo4, check that foo1, foo2 and foo3
75 // inherit attribute from bar
76 mod third {
77 #[must_use = "some reason"]
78 fn bar() {}
79 reuse bar as foo1;
80 reuse foo1 as foo2;
81 reuse foo2 as foo3;
82 #[must_use = "foo4"]
83 reuse foo3 as foo4;
84 reuse foo4 as foo5;
85 }
86
87 mod fourth {
88 trait T {
89 fn foo(&self, x: usize) -> usize { x + 1 }
90 }
91
92 struct X;
93 impl T for X {}
94
95 #[must_use = "some reason"]
96 reuse <X as T>::foo { self + 1 }
97 reuse foo as bar { self + 1 }
98 }
99}
100
101fn main() {}
tests/pretty/delegation/inline-attribute.pp created+92
......@@ -0,0 +1,92 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:inline-attribute.pp
4
5#![allow(incomplete_features)]
6#![attr = Feature([fn_delegation#0])]
7extern crate std;
8#[attr = PreludeImport]
9use ::std::prelude::rust_2015::*;
10
11mod to_reuse {
12 fn foo(x: usize) -> usize { x }
13}
14
15// Check that #[inline(hint)] is added to foo reuse
16#[attr = Inline(Hint)]
17fn bar(arg0: _) -> _ { to_reuse::foo(self + 1) }
18
19trait Trait {
20 fn foo(&self) { }
21 fn foo1(&self) { }
22 fn foo2(&self) { }
23 fn foo3(&self) { }
24 fn foo4(&self) { }
25}
26
27impl Trait for u8 { }
28
29struct S(u8);
30
31mod to_import {
32 fn check(arg: &'_ u8) -> &'_ u8 { arg }
33}
34
35impl Trait for S {
36 // Check that #[inline(hint)] is added to foo reuse
37 #[attr = Inline(Hint)]
38 fn foo(self: _)
39 ->
40 _ {
41 // Check that #[inline(hint)] is added to foo0 reuse inside another reuse
42 #[attr = Inline(Hint)]
43 fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }
44
45 // Check that #[inline(hint)] is added when other attributes present in inner reuse
46 #[attr = Cold]
47 #[attr = MustUse]
48 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
49 #[attr = Inline(Hint)]
50 fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }
51
52 // Check that #[inline(never)] is preserved in inner reuse
53 #[attr = Inline(Never)]
54 fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) }
55
56 // Check that #[inline(always)] is preserved in inner reuse
57 #[attr = Inline(Always)]
58 fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }
59
60 // Check that #[inline(never)] is preserved when there are other attributes in inner reuse
61 #[attr = Cold]
62 #[attr = MustUse]
63 #[attr = Inline(Never)]
64 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
65 fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
66 Trait::foo(self)
67 }
68
69 // Check that #[inline(hint)] is added when there are other attributes present in trait reuse
70 #[attr = Cold]
71 #[attr = MustUse]
72 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
73 #[attr = Inline(Hint)]
74 fn foo1(self: _) -> _ { Trait::foo1(self.0) }
75
76 // Check that #[inline(never)] is preserved in trait reuse
77 #[attr = Inline(Never)]
78 fn foo2(self: _) -> _ { Trait::foo2(self.0) }
79
80 // Check that #[inline(always)] is preserved in trait reuse
81 #[attr = Inline(Always)]
82 fn foo3(self: _) -> _ { Trait::foo3(self.0) }
83
84 // Check that #[inline(never)] is preserved when there are other attributes in trait reuse
85 #[attr = Cold]
86 #[attr = MustUse]
87 #[attr = Inline(Never)]
88 #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}]
89 fn foo4(self: _) -> _ { Trait::foo4(self.0) }
90}
91
92fn main() { }
tests/pretty/delegation/inline-attribute.rs created+104
......@@ -0,0 +1,104 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:inline-attribute.pp
4
5#![allow(incomplete_features)]
6#![feature(fn_delegation)]
7
8mod to_reuse {
9 pub fn foo(x: usize) -> usize {
10 x
11 }
12}
13
14// Check that #[inline(hint)] is added to foo reuse
15reuse to_reuse::foo as bar {
16 self + 1
17}
18
19trait Trait {
20 fn foo(&self) {}
21 fn foo1(&self) {}
22 fn foo2(&self) {}
23 fn foo3(&self) {}
24 fn foo4(&self) {}
25}
26
27impl Trait for u8 {}
28
29struct S(u8);
30
31mod to_import {
32 pub fn check(arg: &u8) -> &u8 { arg }
33}
34
35impl Trait for S {
36 // Check that #[inline(hint)] is added to foo reuse
37 reuse Trait::foo {
38 // Check that #[inline(hint)] is added to foo0 reuse inside another reuse
39 reuse to_reuse::foo as foo0 {
40 self + 1
41 }
42
43 // Check that #[inline(hint)] is added when other attributes present in inner reuse
44 #[cold]
45 #[must_use]
46 #[deprecated]
47 reuse to_reuse::foo as foo1 {
48 self / 2
49 }
50
51 // Check that #[inline(never)] is preserved in inner reuse
52 #[inline(never)]
53 reuse to_reuse::foo as foo2 {
54 self / 2
55 }
56
57 // Check that #[inline(always)] is preserved in inner reuse
58 #[inline(always)]
59 reuse to_reuse::foo as foo3 {
60 self / 2
61 }
62
63 // Check that #[inline(never)] is preserved when there are other attributes in inner reuse
64 #[cold]
65 #[must_use]
66 #[inline(never)]
67 #[deprecated]
68 reuse to_reuse::foo as foo4 {
69 self / 2
70 }
71 }
72
73 // Check that #[inline(hint)] is added when there are other attributes present in trait reuse
74 #[cold]
75 #[must_use]
76 #[deprecated]
77 reuse Trait::foo1 {
78 self.0
79 }
80
81 // Check that #[inline(never)] is preserved in trait reuse
82 #[inline(never)]
83 reuse Trait::foo2 {
84 self.0
85 }
86
87 // Check that #[inline(always)] is preserved in trait reuse
88 #[inline(always)]
89 reuse Trait::foo3 {
90 self.0
91 }
92
93 // Check that #[inline(never)] is preserved when there are other attributes in trait reuse
94 #[cold]
95 #[must_use]
96 #[inline(never)]
97 #[deprecated]
98 reuse Trait::foo4 {
99 self.0
100 }
101}
102
103fn main() {
104}
tests/pretty/delegation/self-rename.pp created+58
......@@ -0,0 +1,58 @@
1#![attr = Feature([fn_delegation#0])]
2extern crate std;
3#[attr = PreludeImport]
4use ::std::prelude::rust_2015::*;
5//@ pretty-compare-only
6//@ pretty-mode:hir
7//@ pp-exact:self-rename.pp
8
9
10trait Trait<'a, A, const B: bool> {
11 fn foo<'b, const B2: bool, T, U,
12 impl FnOnce() -> usize>(&self, f: impl FnOnce() -> usize) -> usize
13 where impl FnOnce() -> usize: FnOnce() -> usize { f() + 1 }
14}
15
16struct X;
17impl <'a, A, const B: bool> Trait<'a, A, B> for X { }
18
19#[attr = Inline(Hint)]
20fn foo<'a, Self, A, const B: _, const B2: _, T, U,
21 impl FnOnce() -> usize>(self: _, arg1: _) -> _ where
22 'a:'a { <Self as Trait::<'a, A, B>>::foo::<B2, T, U>(self, arg1) }
23#[attr = Inline(Hint)]
24fn bar<Self, impl FnOnce() -> usize>(self: _, arg1: _)
25 ->
26 _ {
27 <Self as Trait::<'static, (), true>>::foo::<true, (), ()>(self, arg1)
28}
29
30#[attr = Inline(Hint)]
31fn foo2<'a, This, A, const B: _, const B2: _, T, U,
32 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
33 'a:'a { foo::<'a, This, A, B, B2, T, U>(arg0, arg1) }
34#[attr = Inline(Hint)]
35fn bar2<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
36 -> _ { bar::<This>(arg0, arg1) }
37
38trait Trait2 {
39 #[attr = Inline(Hint)]
40 fn foo3<'a, This, A, const B: _, const B2: _, T, U,
41 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
42 'a:'a { foo2::<'a, This, A, B, B2, T, U>(arg0, arg1) }
43 #[attr = Inline(Hint)]
44 fn bar3<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
45 -> _ { bar2::<This>(arg0, arg1) }
46}
47
48impl Trait2 for () { }
49
50#[attr = Inline(Hint)]
51fn foo4<'a, This, A, const B: _, const B2: _, T, U,
52 impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
53 'a:'a { <() as Trait2>::foo3::<'a, This, A, B, B2, T, U>(arg0, arg1) }
54#[attr = Inline(Hint)]
55fn bar4<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
56 -> _ { <() as Trait2>::bar3::<This>(arg0, arg1) }
57
58fn main() { }
tests/pretty/delegation/self-rename.rs created+32
......@@ -0,0 +1,32 @@
1//@ pretty-compare-only
2//@ pretty-mode:hir
3//@ pp-exact:self-rename.pp
4
5#![feature(fn_delegation)]
6
7trait Trait<'a, A, const B: bool> {
8 fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
9 f() + 1
10 }
11}
12
13struct X;
14impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
15
16reuse Trait::foo;
17reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
18
19reuse foo as foo2;
20reuse bar as bar2;
21
22trait Trait2 {
23 reuse foo2 as foo3;
24 reuse bar2 as bar3;
25}
26
27impl Trait2 for () {}
28
29reuse <() as Trait2>::foo3 as foo4;
30reuse <() as Trait2>::bar3 as bar4;
31
32fn main() {}
tests/ui/attributes/may_dangle.rs+5-5
......@@ -12,7 +12,7 @@ unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {
1212//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
1313
1414unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
15 //~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
15 //~^ ERROR attribute cannot be used on
1616 fn drop(&mut self) {}
1717}
1818
......@@ -39,15 +39,15 @@ mod fake {
3939 }
4040}
4141
42#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
42#[may_dangle] //~ ERROR attribute cannot be used on
4343struct Dangling;
4444
45#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
45#[may_dangle] //~ ERROR attribute cannot be used on
4646impl NotDrop for () {
4747}
4848
49#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
49#[may_dangle] //~ ERROR attribute cannot be used on
5050fn main() {
51 #[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
51 #[may_dangle] //~ ERROR attribute cannot be used on
5252 let () = ();
5353}
tests/ui/attributes/may_dangle.stderr+27-17
......@@ -1,44 +1,54 @@
1error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
2 --> $DIR/may_dangle.rs:8:13
3 |
4LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
5 | ^^^^^^^^^^^^^
6
7error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
8 --> $DIR/may_dangle.rs:11:17
9 |
10LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
11 | ^^^^^^^^^^^^^
12
13error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
1error: `#[may_dangle]` attribute cannot be used on const parameters
142 --> $DIR/may_dangle.rs:14:20
153 |
164LL | unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
175 | ^^^^^^^^^^^^^
6 |
7 = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters
188
19error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
9error: `#[may_dangle]` attribute cannot be used on structs
2010 --> $DIR/may_dangle.rs:42:1
2111 |
2212LL | #[may_dangle]
2313 | ^^^^^^^^^^^^^
14 |
15 = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters
2416
25error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
17error: `#[may_dangle]` attribute cannot be used on trait impl blocks
2618 --> $DIR/may_dangle.rs:45:1
2719 |
2820LL | #[may_dangle]
2921 | ^^^^^^^^^^^^^
22 |
23 = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters
3024
31error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
25error: `#[may_dangle]` attribute cannot be used on functions
3226 --> $DIR/may_dangle.rs:49:1
3327 |
3428LL | #[may_dangle]
3529 | ^^^^^^^^^^^^^
30 |
31 = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters
3632
37error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
33error: `#[may_dangle]` attribute cannot be used on statements
3834 --> $DIR/may_dangle.rs:51:5
3935 |
4036LL | #[may_dangle]
4137 | ^^^^^^^^^^^^^
38 |
39 = help: `#[may_dangle]` can be applied to lifetime parameters and type parameters
40
41error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
42 --> $DIR/may_dangle.rs:8:13
43 |
44LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
45 | ^^^^^^^^^^^^^
46
47error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
48 --> $DIR/may_dangle.rs:11:17
49 |
50LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
51 | ^^^^^^^^^^^^^
4252
4353error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
4454 --> $DIR/may_dangle.rs:36:17
tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs created+11
......@@ -0,0 +1,11 @@
1#![feature(min_generic_const_args)]
2
3trait A<T> {}
4trait Trait<const N: usize> {}
5
6impl A<[usize; fn_item]> for () {}
7
8fn fn_item(_: impl Trait<usize>) {}
9//~^ ERROR: type provided when a constant was expected
10
11fn main() {}
tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.stderr created+14
......@@ -0,0 +1,14 @@
1error[E0747]: type provided when a constant was expected
2 --> $DIR/synth-gen-arg-ice-158152.rs:8:26
3 |
4LL | fn fn_item(_: impl Trait<usize>) {}
5 | ^^^^^
6 |
7help: if this generic argument was intended as a const parameter, surround it with braces
8 |
9LL | fn fn_item(_: impl Trait<{ usize }>) {}
10 | + +
11
12error: aborting due to 1 previous error
13
14For more information about this error, try `rustc --explain E0747`.
tests/ui/delegation/generics/infer-defaults.rs created+124
......@@ -0,0 +1,124 @@
1#![feature(fn_delegation)]
2
3mod free_to_trait {
4 trait Trait<'a, XX, Y, T = (), const N: usize = 2> {
5 fn foo<A, B>(&self, t: (T, A, B), slice: &[usize; N]) {}
6 }
7
8 struct X;
9 impl<XX, Y, T, const N: usize> Trait<'_, XX, Y, T, N> for X {}
10
11 // When infer is specified for default parameter the generic param is generated.
12 reuse Trait::<'_, _, _, _, _>::foo as foo;
13 // When default params are omitted they are not generated but used in signature inheritance.
14 reuse Trait::<'_, _, _>::foo as bar;
15
16 // Check with user specified args in child:
17 // When infer is specified for default parameter the generic param is generated.
18 reuse Trait::<'_, _, _, _, _>::foo::<(), _> as foo1;
19 // When default params are omitted they are not generated but used in signature inheritance.
20 reuse Trait::<'_, _, _>::foo::<_, ()> as bar1;
21
22 // Check with explicit self type.
23 reuse <X as Trait::<'_, _, _, _, _>>::foo as foo2;
24 reuse <X as Trait::<'_, _, _>>::foo as bar2;
25
26 reuse <X as Trait::<'_, _, _, _, _>>::foo::<(), _> as foo3;
27 reuse <X as Trait::<'_, _, _>>::foo::<_, ()> as bar3;
28
29 fn check() {
30 foo::<'static, X, (), (), (), 1, (), ()>(&X, ((), (), ()), &[1]);
31 bar::<'static, X, (), (), (), ()>(&X, ((), (), ()), &[1, 2]);
32
33 foo1::<'static, X, (), (), (), 2, ()>(&X, ((), (), ()), &[1, 2]);
34 bar1::<'static, X, (), (), ()>(&X, ((), (), ()), &[1, 2]);
35
36 foo2::<'static, (), (), (), 3, (), ()>(&X, ((), (), ()), &[1, 2, 3]);
37 bar2::<'static, (), (), (), ()>(&X, ((), (), ()), &[1, 2]);
38
39 foo3::<'static, (), (), (), 4, ()>(&X, ((), (), ()), &[1, 2, 3, 4]);
40 bar3::<'static, (), (), ()>(&X, ((), (), ()), &[1, 2]);
41 }
42}
43
44mod trait_to_trait {
45 trait Trait<'a, X, Y, T = (), const N: usize = 2> {
46 fn foo(&self, t: (T, T, T), slice: &[usize; N]) {}
47 fn bar(&self, t: (T, T, T), slice: &[usize; N]) {}
48 }
49
50 trait Trait2<'a, X, Y>: Trait<'a, X, Y> {
51 // Default params are generated as usual generics as infers are specified.
52 reuse Trait::<'a, X, Y, _, _>::foo;
53 //~^ ERROR: the trait bound `Self: trait_to_trait::Trait<'a, X, Y, T, N>` is not satisfied
54
55 // Default params are not generated, as they are not specified.
56 reuse Trait::<'a, X, Y>::foo as bar;
57 }
58
59 impl Trait<'static, (), ()> for () {}
60 impl Trait2<'static, (), ()> for () {}
61
62 fn check() {
63 Trait2::<'static, (), ()>::foo::<(), 1>(&(), ((), (), ()), &[1]);
64 Trait2::<'static, (), ()>::bar(&(), ((), (), ()), &[1, 2]);
65 }
66}
67
68mod trait_impl_to_trait {
69 trait Trait<'a, X, Y, T = (), const N: usize = 2> {
70 fn foo(&self, t: (T, T, T), slice: &[usize; N]) {}
71 fn bar(&self, t: (T, T, T), slice: &[usize; N]) {}
72 }
73
74 struct S;
75 impl<X, Y> Trait<'_, X, Y> for S {}
76
77 struct W(S);
78 impl<X, Y> Trait<'_, X, Y> for W {
79 // Generics of both methods match generics of their signature
80 // functions in `Trait` declaration, no matter specified infers.
81 reuse Trait::<'static, X, Y>::foo { self.0 }
82 reuse Trait::<'static, X, Y, _, _>::foo as bar { self.0 }
83 }
84
85 fn check() {
86 W(S).foo(((), (), ()), &[1, 2]);
87 W(S).foo::<1, 2, 3>(((), (), ()), &[1, 2]);
88 //~^ ERROR: method takes 0 generic arguments but 3 generic arguments were supplied
89
90 W(S).bar(((), (), ()), &[1]);
91 //~^ ERROR: mismatched types
92 W(S).bar::<((), ()), 0>(((), (), ()), &[1, 2]);
93 //~^ ERROR: method takes 0 generic arguments but 2 generic arguments were supplied
94
95 W(S).bar(((), (), ()), &[1, 2]);
96 }
97}
98
99mod inherent_impl_to_trait {
100 trait Trait<'a, X, Y, T = (), const N: usize = 2> {
101 fn foo(&self, t: (T, T, T), slice: &[usize; N]) {}
102 }
103
104 struct S<T>(T);
105
106 impl<T: Trait<'static, (), ()>> S<T> {
107 // Default params are not generated, as they are not specified.
108 reuse Trait::<'static, (), ()>::foo { self.0 }
109
110 // Default params are generated as usual generics as infers are specified.
111 reuse Trait::<'static, (), (), _, _>::foo as bar { self.0 }
112 //~^ ERROR: the trait bound `T: inherent_impl_to_trait::Trait<'static, (), (), T, N>` is not satisfied
113 }
114
115 impl Trait<'static, (), ()> for () {}
116
117 fn check() {
118 S(()).foo(((), (), ()), &[1, 2]);
119 S(()).bar(((), (), ()), &[1, 2]);
120 S(()).bar::<usize, 4>((1, 2, 3), &[1, 2, 3, 4]);
121 }
122}
123
124fn main() {}
tests/ui/delegation/generics/infer-defaults.stderr created+70
......@@ -0,0 +1,70 @@
1error[E0277]: the trait bound `Self: trait_to_trait::Trait<'a, X, Y, T, N>` is not satisfied
2 --> $DIR/infer-defaults.rs:52:40
3 |
4LL | reuse Trait::<'a, X, Y, _, _>::foo;
5 | ^^^ the trait `trait_to_trait::Trait<'a, X, Y, T, N>` is not implemented for `Self`
6 |
7help: consider further restricting `Self`
8 |
9LL | reuse Trait::<'a, X, Y, _, _>::foo Self: trait_to_trait::Trait<'a, X, Y, T, N>;
10 | +++++++++++++++++++++++++++++++++++++++++++
11
12error[E0107]: method takes 0 generic arguments but 3 generic arguments were supplied
13 --> $DIR/infer-defaults.rs:87:14
14 |
15LL | W(S).foo::<1, 2, 3>(((), (), ()), &[1, 2]);
16 | ^^^----------- help: remove the unnecessary generics
17 | |
18 | expected 0 generic arguments
19 |
20note: method defined here, with 0 generic parameters
21 --> $DIR/infer-defaults.rs:70:12
22 |
23LL | fn foo(&self, t: (T, T, T), slice: &[usize; N]) {}
24 | ^^^
25
26error[E0308]: mismatched types
27 --> $DIR/infer-defaults.rs:90:32
28 |
29LL | W(S).bar(((), (), ()), &[1]);
30 | --- ^^^^ expected an array with a size of 2, found one with a size of 1
31 | |
32 | arguments to this method are incorrect
33 |
34note: method defined here
35 --> $DIR/infer-defaults.rs:71:12
36 |
37LL | fn bar(&self, t: (T, T, T), slice: &[usize; N]) {}
38 | ^^^ ------------------
39
40error[E0107]: method takes 0 generic arguments but 2 generic arguments were supplied
41 --> $DIR/infer-defaults.rs:92:14
42 |
43LL | W(S).bar::<((), ()), 0>(((), (), ()), &[1, 2]);
44 | ^^^--------------- help: remove the unnecessary generics
45 | |
46 | expected 0 generic arguments
47 |
48note: method defined here, with 0 generic parameters
49 --> $DIR/infer-defaults.rs:71:12
50 |
51LL | fn bar(&self, t: (T, T, T), slice: &[usize; N]) {}
52 | ^^^
53
54error[E0277]: the trait bound `T: inherent_impl_to_trait::Trait<'static, (), (), T, N>` is not satisfied
55 --> $DIR/infer-defaults.rs:111:60
56 |
57LL | reuse Trait::<'static, (), (), _, _>::foo as bar { self.0 }
58 | --- ^^^^^^ the trait `inherent_impl_to_trait::Trait<'static, (), (), T, N>` is not implemented for `T`
59 | |
60 | required by a bound introduced by this call
61 |
62help: consider restricting type parameter `T` with trait `Trait`
63 |
64LL | reuse Trait::<'static, (), (), _, _>::foo inherent_impl_to_trait::Trait<'static, (), (), T, N> as bar { self.0 }
65 | ++++++++++++++++++++++++++++++++++++++++++++++++++++
66
67error: aborting due to 5 previous errors
68
69Some errors have detailed explanations: E0107, E0277, E0308.
70For more information about an error, try `rustc --explain E0107`.
tests/ui/macros/deref-raw-pointer-issue-158158.rs created+21
......@@ -0,0 +1,21 @@
1struct Demo {
2 val: u32,
3}
4
5macro_rules! as_ptr {
6 ($d:expr) => {
7 &mut $d as *mut Demo
8 };
9}
10
11macro_rules! get_value {
12 ($d:expr) => {
13 as_ptr!($d).val
14 //~^ ERROR no field `val` on type `*mut Demo`
15 }
16}
17
18fn main() {
19 let mut d = Demo { val: 123 };
20 let _ = get_value!(d);
21}
tests/ui/macros/deref-raw-pointer-issue-158158.stderr created+14
......@@ -0,0 +1,14 @@
1error[E0609]: no field `val` on type `*mut Demo`
2 --> $DIR/deref-raw-pointer-issue-158158.rs:13:21
3 |
4LL | as_ptr!($d).val
5 | ^^^ unknown field
6...
7LL | let _ = get_value!(d);
8 | ------------- in this macro invocation
9 |
10 = note: this error originates in the macro `get_value` (in Nightly builds, run with -Z macro-backtrace for more info)
11
12error: aborting due to 1 previous error
13
14For more information about this error, try `rustc --explain E0609`.