Skip to content

Commit ff24ef9

Browse files
committedApr 9, 2024
Auto merge of #123676 - GuillaumeGomez:rollup-1hurixy, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #123254 (Do not allocate for ZST ThinBox (attempt 2 using const_allocate)) - #123626 (Add MC/DC support to coverage test tools) - #123638 (rustdoc: synthetic auto: filter out clauses from the implementor's ParamEnv) - #123653 (Split `non_local_definitions` lint tests in separate test files) - #123658 (Stop making any assumption about the projections applied to the upvars in the `ByMoveBody` pass) - #123662 (Don't rely on upvars being assigned just because coroutine-closure kind is assigned) - #123665 (Fix typo in `Future::poll()` docs) - #123672 (compiletest: unset `RUSTC_LOG_COLOR`) r? `@ghost` `@rustbot` modify labels: rollup
·
1.90.01.79.0
2 parents 2805aed + ed43ac6 commit ff24ef9

39 files changed

+1691
-1321
lines changed
 

‎compiler/rustc_middle/src/ty/sty.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ impl<'tcx> Ty<'tcx> {
22312231
pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
22322232
match self.kind() {
22332233
Tuple(args) => args,
2234-
_ => bug!("tuple_fields called on non-tuple"),
2234+
_ => bug!("tuple_fields called on non-tuple: {self:?}"),
22352235
}
22362236
}
22372237

‎compiler/rustc_mir_transform/src/coroutine/by_move_body.rs‎

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -281,14 +281,14 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
281281
if place.local == ty::CAPTURE_STRUCT_LOCAL
282282
&& let Some((&mir::ProjectionElem::Field(idx, _), projection)) =
283283
place.projection.split_first()
284-
&& let Some(&(remapped_idx, remapped_ty, needs_deref, additional_projections)) =
284+
&& let Some(&(remapped_idx, remapped_ty, needs_deref, bridging_projections)) =
285285
self.field_remapping.get(&idx)
286286
{
287287
// As noted before, if the parent closure captures a field by value, and
288288
// the child captures a field by ref, then for the by-move body we're
289289
// generating, we also are taking that field by value. Peel off a deref,
290-
// since a layer of reffing has now become redundant.
291-
let final_deref = if needs_deref {
290+
// since a layer of ref'ing has now become redundant.
291+
let final_projections = if needs_deref {
292292
let Some((mir::ProjectionElem::Deref, projection)) = projection.split_first()
293293
else {
294294
bug!(
@@ -302,20 +302,18 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
302302
projection
303303
};
304304

305-
// The only thing that should be left is a deref, if the parent captured
306-
// an upvar by-ref.
307-
std::assert_matches::assert_matches!(final_deref, [] | [mir::ProjectionElem::Deref]);
308-
309-
// For all of the additional projections that come out of precise capturing,
310-
// re-apply these projections.
311-
let additional_projections =
312-
additional_projections.iter().map(|elem| match elem.kind {
313-
ProjectionKind::Deref => mir::ProjectionElem::Deref,
314-
ProjectionKind::Field(idx, VariantIdx::ZERO) => {
315-
mir::ProjectionElem::Field(idx, elem.ty)
316-
}
317-
_ => unreachable!("precise captures only through fields and derefs"),
318-
});
305+
// These projections are applied in order to "bridge" the local that we are
306+
// currently transforming *from* the old upvar that the by-ref coroutine used
307+
// to capture *to* the upvar of the parent coroutine-closure. For example, if
308+
// the parent captures `&s` but the child captures `&(s.field)`, then we will
309+
// apply a field projection.
310+
let bridging_projections = bridging_projections.iter().map(|elem| match elem.kind {
311+
ProjectionKind::Deref => mir::ProjectionElem::Deref,
312+
ProjectionKind::Field(idx, VariantIdx::ZERO) => {
313+
mir::ProjectionElem::Field(idx, elem.ty)
314+
}
315+
_ => unreachable!("precise captures only through fields and derefs"),
316+
});
319317

320318
// We start out with an adjusted field index (and ty), representing the
321319
// upvar that we get from our parent closure. We apply any of the additional
@@ -326,8 +324,8 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
326324
projection: self.tcx.mk_place_elems_from_iter(
327325
[mir::ProjectionElem::Field(remapped_idx, remapped_ty)]
328326
.into_iter()
329-
.chain(additional_projections)
330-
.chain(final_deref.iter().copied()),
327+
.chain(bridging_projections)
328+
.chain(final_projections.iter().copied()),
331329
),
332330
};
333331
}

‎compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
292292
let kind_ty = args.kind_ty();
293293
let sig = args.coroutine_closure_sig().skip_binder();
294294

295-
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
295+
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
296+
&& !args.tupled_upvars_ty().is_ty_var()
297+
{
296298
if !closure_kind.extends(goal_kind) {
297299
return Err(NoSolution);
298300
}
@@ -401,7 +403,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
401403
let kind_ty = args.kind_ty();
402404
let sig = args.coroutine_closure_sig().skip_binder();
403405
let mut nested = vec![];
404-
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
406+
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
407+
&& !args.tupled_upvars_ty().is_ty_var()
408+
{
405409
if !closure_kind.extends(goal_kind) {
406410
return Err(NoSolution);
407411
}

‎compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
487487
bug!();
488488
};
489489

490+
// Bail if the upvars haven't been constrained.
491+
if tupled_upvars_ty.expect_ty().is_ty_var() {
492+
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
493+
}
494+
490495
let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
491496
// We don't need to worry about the self type being an infer var.
492497
return Err(NoSolution);

‎compiler/rustc_trait_selection/src/traits/project.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,10 @@ fn confirm_closure_candidate<'cx, 'tcx>(
16011601
// If we know the kind and upvars, use that directly.
16021602
// Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay
16031603
// the projection, like the `AsyncFn*` traits do.
1604-
let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind() {
1604+
let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind()
1605+
// Fall back to projection if upvars aren't constrained
1606+
&& !args.tupled_upvars_ty().is_ty_var()
1607+
{
16051608
sig.to_coroutine_given_kind_and_upvars(
16061609
tcx,
16071610
args.parent_args(),
@@ -1731,7 +1734,10 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
17311734

17321735
let term = match item_name {
17331736
sym::CallOnceFuture | sym::CallRefFuture => {
1734-
if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
1737+
if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
1738+
// Fall back to projection if upvars aren't constrained
1739+
&& !args.tupled_upvars_ty().is_ty_var()
1740+
{
17351741
if !closure_kind.extends(goal_kind) {
17361742
bug!("we should not be confirming if the closure kind is not met");
17371743
}

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs‎

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -400,39 +400,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
400400
}
401401
}
402402
ty::CoroutineClosure(def_id, args) => {
403+
let args = args.as_coroutine_closure();
403404
let is_const = self.tcx().is_const_fn_raw(def_id);
404-
match self.infcx.closure_kind(self_ty) {
405-
Some(closure_kind) => {
406-
let no_borrows = match self
407-
.infcx
408-
.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty())
409-
.kind()
410-
{
411-
ty::Tuple(tys) => tys.is_empty(),
412-
ty::Error(_) => false,
413-
_ => bug!("tuple_fields called on non-tuple"),
414-
};
415-
// A coroutine-closure implements `FnOnce` *always*, since it may
416-
// always be called once. It additionally implements `Fn`/`FnMut`
417-
// only if it has no upvars (therefore no borrows from the closure
418-
// that would need to be represented with a lifetime) and if the
419-
// closure kind permits it.
420-
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
421-
// if it takes all of its upvars by copy, and none by ref. This would
422-
// require us to record a bit more information during upvar analysis.
423-
if no_borrows && closure_kind.extends(kind) {
424-
candidates.vec.push(ClosureCandidate { is_const });
425-
} else if kind == ty::ClosureKind::FnOnce {
426-
candidates.vec.push(ClosureCandidate { is_const });
427-
}
405+
if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
406+
// Ambiguity if upvars haven't been constrained yet
407+
&& !args.tupled_upvars_ty().is_ty_var()
408+
{
409+
let no_borrows = match args.tupled_upvars_ty().kind() {
410+
ty::Tuple(tys) => tys.is_empty(),
411+
ty::Error(_) => false,
412+
_ => bug!("tuple_fields called on non-tuple"),
413+
};
414+
// A coroutine-closure implements `FnOnce` *always*, since it may
415+
// always be called once. It additionally implements `Fn`/`FnMut`
416+
// only if it has no upvars (therefore no borrows from the closure
417+
// that would need to be represented with a lifetime) and if the
418+
// closure kind permits it.
419+
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
420+
// if it takes all of its upvars by copy, and none by ref. This would
421+
// require us to record a bit more information during upvar analysis.
422+
if no_borrows && closure_kind.extends(kind) {
423+
candidates.vec.push(ClosureCandidate { is_const });
424+
} else if kind == ty::ClosureKind::FnOnce {
425+
candidates.vec.push(ClosureCandidate { is_const });
428426
}
429-
None => {
430-
if kind == ty::ClosureKind::FnOnce {
431-
candidates.vec.push(ClosureCandidate { is_const });
432-
} else {
433-
// This stays ambiguous until kind+upvars are determined.
434-
candidates.ambiguous = true;
435-
}
427+
} else {
428+
if kind == ty::ClosureKind::FnOnce {
429+
candidates.vec.push(ClosureCandidate { is_const });
430+
} else {
431+
// This stays ambiguous until kind+upvars are determined.
432+
candidates.ambiguous = true;
436433
}
437434
}
438435
}

‎library/alloc/src/boxed/thin.rs‎

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
use crate::alloc::{self, Layout, LayoutError};
55
use core::error::Error;
66
use core::fmt::{self, Debug, Display, Formatter};
7+
#[cfg(not(no_global_oom_handling))]
8+
use core::intrinsics::const_allocate;
79
use core::marker::PhantomData;
810
#[cfg(not(no_global_oom_handling))]
911
use core::marker::Unsize;
10-
use core::mem::{self, SizedTypeProperties};
12+
use core::mem;
13+
#[cfg(not(no_global_oom_handling))]
14+
use core::mem::SizedTypeProperties;
1115
use core::ops::{Deref, DerefMut};
1216
use core::ptr::Pointee;
1317
use core::ptr::{self, NonNull};
@@ -109,9 +113,14 @@ impl<Dyn: ?Sized> ThinBox<Dyn> {
109113
where
110114
T: Unsize<Dyn>,
111115
{
112-
let meta = ptr::metadata(&value as &Dyn);
113-
let ptr = WithOpaqueHeader::new(meta, value);
114-
ThinBox { ptr, _marker: PhantomData }
116+
if mem::size_of::<T>() == 0 {
117+
let ptr = WithOpaqueHeader::new_unsize_zst::<Dyn, T>(value);
118+
ThinBox { ptr, _marker: PhantomData }
119+
} else {
120+
let meta = ptr::metadata(&value as &Dyn);
121+
let ptr = WithOpaqueHeader::new(meta, value);
122+
ThinBox { ptr, _marker: PhantomData }
123+
}
115124
}
116125
}
117126

@@ -200,6 +209,16 @@ impl WithOpaqueHeader {
200209
Self(ptr.0)
201210
}
202211

212+
#[cfg(not(no_global_oom_handling))]
213+
fn new_unsize_zst<Dyn, T>(value: T) -> Self
214+
where
215+
Dyn: ?Sized,
216+
T: Unsize<Dyn>,
217+
{
218+
let ptr = WithHeader::<<Dyn as Pointee>::Metadata>::new_unsize_zst::<Dyn, T>(value);
219+
Self(ptr.0)
220+
}
221+
203222
fn try_new<H, T>(header: H, value: T) -> Result<Self, core::alloc::AllocError> {
204223
WithHeader::try_new(header, value).map(|ptr| Self(ptr.0))
205224
}
@@ -288,6 +307,58 @@ impl<H> WithHeader<H> {
288307
}
289308
}
290309

310+
// `Dyn` is `?Sized` type like `[u32]`, and `T` is ZST type like `[u32; 0]`.
311+
#[cfg(not(no_global_oom_handling))]
312+
fn new_unsize_zst<Dyn, T>(value: T) -> WithHeader<H>
313+
where
314+
Dyn: Pointee<Metadata = H> + ?Sized,
315+
T: Unsize<Dyn>,
316+
{
317+
assert!(mem::size_of::<T>() == 0);
318+
319+
const fn max(a: usize, b: usize) -> usize {
320+
if a > b { a } else { b }
321+
}
322+
323+
// Compute a pointer to the right metadata. This will point to the beginning
324+
// of the header, past the padding, so the assigned type makes sense.
325+
// It also ensures that the address at the end of the header is sufficiently
326+
// aligned for T.
327+
let alloc: &<Dyn as Pointee>::Metadata = const {
328+
// FIXME: just call `WithHeader::alloc_layout` with size reset to 0.
329+
// Currently that's blocked on `Layout::extend` not being `const fn`.
330+
331+
let alloc_align =
332+
max(mem::align_of::<T>(), mem::align_of::<<Dyn as Pointee>::Metadata>());
333+
334+
let alloc_size =
335+
max(mem::align_of::<T>(), mem::size_of::<<Dyn as Pointee>::Metadata>());
336+
337+
unsafe {
338+
// SAFETY: align is power of two because it is the maximum of two alignments.
339+
let alloc: *mut u8 = const_allocate(alloc_size, alloc_align);
340+
341+
let metadata_offset =
342+
alloc_size.checked_sub(mem::size_of::<<Dyn as Pointee>::Metadata>()).unwrap();
343+
// SAFETY: adding offset within the allocation.
344+
let metadata_ptr: *mut <Dyn as Pointee>::Metadata =
345+
alloc.add(metadata_offset).cast();
346+
// SAFETY: `*metadata_ptr` is within the allocation.
347+
metadata_ptr.write(ptr::metadata::<Dyn>(ptr::dangling::<T>() as *const Dyn));
348+
349+
// SAFETY: we have just written the metadata.
350+
&*(metadata_ptr)
351+
}
352+
};
353+
354+
// SAFETY: `alloc` points to `<Dyn as Pointee>::Metadata`, so addition stays in-bounds.
355+
let value_ptr =
356+
unsafe { (alloc as *const <Dyn as Pointee>::Metadata).add(1) }.cast::<T>().cast_mut();
357+
debug_assert!(value_ptr.is_aligned());
358+
mem::forget(value);
359+
WithHeader(NonNull::new(value_ptr.cast()).unwrap(), PhantomData)
360+
}
361+
291362
// Safety:
292363
// - Assumes that either `value` can be dereferenced, or is the
293364
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
@@ -300,20 +371,19 @@ impl<H> WithHeader<H> {
300371

301372
impl<H> Drop for DropGuard<H> {
302373
fn drop(&mut self) {
374+
// All ZST are allocated statically.
375+
if self.value_layout.size() == 0 {
376+
return;
377+
}
378+
303379
unsafe {
304380
// SAFETY: Layout must have been computable if we're in drop
305381
let (layout, value_offset) =
306382
WithHeader::<H>::alloc_layout(self.value_layout).unwrap_unchecked();
307383

308-
// Note: Don't deallocate if the layout size is zero, because the pointer
309-
// didn't come from the allocator.
310-
if layout.size() != 0 {
311-
alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
312-
} else {
313-
debug_assert!(
314-
value_offset == 0 && H::IS_ZST && self.value_layout.size() == 0
315-
);
316-
}
384+
// Since we only allocate for non-ZSTs, the layout size cannot be zero.
385+
debug_assert!(layout.size() != 0);
386+
alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
317387
}
318388
}
319389
}

‎library/alloc/src/lib.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@
108108
#![feature(const_box)]
109109
#![feature(const_cow_is_borrowed)]
110110
#![feature(const_eval_select)]
111+
#![feature(const_heap)]
111112
#![feature(const_maybe_uninit_as_mut_ptr)]
112113
#![feature(const_maybe_uninit_write)]
114+
#![feature(const_option)]
113115
#![feature(const_pin)]
114116
#![feature(const_refs_to_cell)]
115117
#![feature(const_size_of_val)]

‎library/core/src/future/future.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub trait Future {
8181
/// An implementation of `poll` should strive to return quickly, and should
8282
/// not block. Returning quickly prevents unnecessarily clogging up
8383
/// threads or event loops. If it is known ahead of time that a call to
84-
/// `poll` may end up taking awhile, the work should be offloaded to a
84+
/// `poll` may end up taking a while, the work should be offloaded to a
8585
/// thread pool (or something similar) to ensure that `poll` can return
8686
/// quickly.
8787
///

‎src/librustdoc/clean/auto_trait.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ fn clean_param_env<'tcx>(
168168

169169
// FIXME(#111101): Incorporate the explicit predicates of the item here...
170170
let item_predicates: FxIndexSet<_> =
171-
tcx.predicates_of(item_def_id).predicates.iter().map(|(pred, _)| pred).collect();
171+
tcx.param_env(item_def_id).caller_bounds().iter().collect();
172172
let where_predicates = param_env
173173
.caller_bounds()
174174
.iter()

‎src/tools/compiletest/src/header.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ impl TestProps {
266266
aux_crates: vec![],
267267
revisions: vec![],
268268
rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
269-
unset_rustc_env: vec![],
269+
unset_rustc_env: vec![("RUSTC_LOG_COLOR".to_string())],
270270
exec_env: vec![],
271271
unset_exec_env: vec![],
272272
build_aux_docs: false,

‎src/tools/compiletest/src/runtest.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,19 @@ impl<'test> TestCx<'test> {
752752
Lazy::new(|| Regex::new(r"(?m:^)(?<prefix>(?: \|)+ Branch \()[0-9]+:").unwrap());
753753
let coverage = BRANCH_LINE_NUMBER_RE.replace_all(&coverage, "${prefix}LL:");
754754

755+
// ` |---> MC/DC Decision Region (1:30) to (2:` => ` |---> MC/DC Decision Region (LL:30) to (LL:`
756+
static MCDC_DECISION_LINE_NUMBER_RE: Lazy<Regex> = Lazy::new(|| {
757+
Regex::new(r"(?m:^)(?<prefix>(?: \|)+---> MC/DC Decision Region \()[0-9]+:(?<middle>[0-9]+\) to \()[0-9]+:").unwrap()
758+
});
759+
let coverage =
760+
MCDC_DECISION_LINE_NUMBER_RE.replace_all(&coverage, "${prefix}LL:${middle}LL:");
761+
762+
// ` | Condition C1 --> (1:` => ` | Condition C1 --> (LL:`
763+
static MCDC_CONDITION_LINE_NUMBER_RE: Lazy<Regex> = Lazy::new(|| {
764+
Regex::new(r"(?m:^)(?<prefix>(?: \|)+ Condition C[0-9]+ --> \()[0-9]+:").unwrap()
765+
});
766+
let coverage = MCDC_CONDITION_LINE_NUMBER_RE.replace_all(&coverage, "${prefix}LL:");
767+
755768
coverage.into_owned()
756769
}
757770

‎src/tools/compiletest/src/runtest/tests.rs‎

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -50,72 +50,68 @@ fn normalize_platform_differences() {
5050
}
5151

5252
/// Test for anonymizing line numbers in coverage reports, especially for
53-
/// branch regions.
53+
/// MC/DC regions.
5454
///
55-
/// FIXME(#119681): This test can be removed when we have examples of branch
55+
/// FIXME(#123409): This test can be removed when we have examples of MC/DC
5656
/// coverage in the actual coverage test suite.
5757
#[test]
5858
fn anonymize_coverage_line_numbers() {
5959
let anon = |coverage| TestCx::anonymize_coverage_line_numbers(coverage);
6060

6161
let input = r#"
62-
6| 3|fn print_size<T>() {
63-
7| 3| if std::mem::size_of::<T>() > 4 {
62+
7| 2|fn mcdc_check_neither(a: bool, b: bool) {
63+
8| 2| if a && b {
64+
^0
6465
------------------
65-
| Branch (7:8): [True: 0, False: 1]
66-
| Branch (7:8): [True: 0, False: 1]
67-
| Branch (7:8): [True: 1, False: 0]
66+
|---> MC/DC Decision Region (8:8) to (8:14)
67+
|
68+
| Number of Conditions: 2
69+
| Condition C1 --> (8:8)
70+
| Condition C2 --> (8:13)
71+
|
72+
| Executed MC/DC Test Vectors:
73+
|
74+
| C1, C2 Result
75+
| 1 { F, - = F }
76+
|
77+
| C1-Pair: not covered
78+
| C2-Pair: not covered
79+
| MC/DC Coverage for Decision: 0.00%
80+
|
6881
------------------
69-
8| 1| println!("size > 4");
82+
9| 0| say("a and b");
83+
10| 2| } else {
84+
11| 2| say("not both");
85+
12| 2| }
86+
13| 2|}
7087
"#;
7188

7289
let expected = r#"
73-
LL| 3|fn print_size<T>() {
74-
LL| 3| if std::mem::size_of::<T>() > 4 {
90+
LL| 2|fn mcdc_check_neither(a: bool, b: bool) {
91+
LL| 2| if a && b {
92+
^0
7593
------------------
76-
| Branch (LL:8): [True: 0, False: 1]
77-
| Branch (LL:8): [True: 0, False: 1]
78-
| Branch (LL:8): [True: 1, False: 0]
79-
------------------
80-
LL| 1| println!("size > 4");
81-
"#;
82-
83-
assert_eq!(anon(input), expected);
84-
85-
//////////
86-
87-
let input = r#"
88-
12| 3|}
89-
------------------
90-
| branch_generics::print_size::<()>:
91-
| 6| 1|fn print_size<T>() {
92-
| 7| 1| if std::mem::size_of::<T>() > 4 {
93-
| ------------------
94-
| | Branch (7:8): [True: 0, False: 1]
95-
| ------------------
96-
| 8| 0| println!("size > 4");
97-
| 9| 1| } else {
98-
| 10| 1| println!("size <= 4");
99-
| 11| 1| }
100-
| 12| 1|}
101-
------------------
102-
"#;
103-
104-
let expected = r#"
105-
LL| 3|}
106-
------------------
107-
| branch_generics::print_size::<()>:
108-
| LL| 1|fn print_size<T>() {
109-
| LL| 1| if std::mem::size_of::<T>() > 4 {
110-
| ------------------
111-
| | Branch (LL:8): [True: 0, False: 1]
112-
| ------------------
113-
| LL| 0| println!("size > 4");
114-
| LL| 1| } else {
115-
| LL| 1| println!("size <= 4");
116-
| LL| 1| }
117-
| LL| 1|}
94+
|---> MC/DC Decision Region (LL:8) to (LL:14)
95+
|
96+
| Number of Conditions: 2
97+
| Condition C1 --> (LL:8)
98+
| Condition C2 --> (LL:13)
99+
|
100+
| Executed MC/DC Test Vectors:
101+
|
102+
| C1, C2 Result
103+
| 1 { F, - = F }
104+
|
105+
| C1-Pair: not covered
106+
| C2-Pair: not covered
107+
| MC/DC Coverage for Decision: 0.00%
108+
|
118109
------------------
110+
LL| 0| say("a and b");
111+
LL| 2| } else {
112+
LL| 2| say("not both");
113+
LL| 2| }
114+
LL| 2|}
119115
"#;
120116

121117
assert_eq!(anon(input), expected);

‎src/tools/coverage-dump/src/covfun.rs‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ pub(crate) fn dump_covfun_mappings(
7070
}
7171
// If the mapping is a branch region, print both of its arms
7272
// in resolved form (even if they aren't expressions).
73-
MappingKind::Branch { r#true, r#false } => {
73+
MappingKind::Branch { r#true, r#false }
74+
| MappingKind::MCDCBranch { r#true, r#false, .. } => {
7475
println!(" true = {}", expression_resolver.format_term(r#true));
7576
println!(" false = {}", expression_resolver.format_term(r#false));
7677
}
@@ -164,6 +165,26 @@ impl<'a> Parser<'a> {
164165
let r#false = self.read_simple_term()?;
165166
Ok(MappingKind::Branch { r#true, r#false })
166167
}
168+
5 => {
169+
let bitmap_idx = self.read_uleb128_u32()?;
170+
let conditions_num = self.read_uleb128_u32()?;
171+
Ok(MappingKind::MCDCDecision { bitmap_idx, conditions_num })
172+
}
173+
6 => {
174+
let r#true = self.read_simple_term()?;
175+
let r#false = self.read_simple_term()?;
176+
let condition_id = self.read_uleb128_u32()?;
177+
let true_next_id = self.read_uleb128_u32()?;
178+
let false_next_id = self.read_uleb128_u32()?;
179+
Ok(MappingKind::MCDCBranch {
180+
r#true,
181+
r#false,
182+
condition_id,
183+
true_next_id,
184+
false_next_id,
185+
})
186+
}
187+
167188
_ => Err(anyhow!("unknown mapping kind: {raw_mapping_kind:#x}")),
168189
}
169190
}
@@ -224,7 +245,28 @@ enum MappingKind {
224245
// Using raw identifiers here makes the dump output a little bit nicer
225246
// (via the derived Debug), at the expense of making this tool's source
226247
// code a little bit uglier.
227-
Branch { r#true: CovTerm, r#false: CovTerm },
248+
Branch {
249+
r#true: CovTerm,
250+
r#false: CovTerm,
251+
},
252+
MCDCBranch {
253+
r#true: CovTerm,
254+
r#false: CovTerm,
255+
// These attributes are printed in Debug but not used directly.
256+
#[allow(dead_code)]
257+
condition_id: u32,
258+
#[allow(dead_code)]
259+
true_next_id: u32,
260+
#[allow(dead_code)]
261+
false_next_id: u32,
262+
},
263+
MCDCDecision {
264+
// These attributes are printed in Debug but not used directly.
265+
#[allow(dead_code)]
266+
bitmap_idx: u32,
267+
#[allow(dead_code)]
268+
conditions_num: u32,
269+
},
228270
}
229271

230272
struct MappingRegion {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Check that we don't add bounds to synthetic auto trait impls that are
2+
// already implied by the item (like supertrait bounds).
3+
4+
// In this case we don't want to add the bounds `T: Copy` and `T: 'static`
5+
// to the auto trait impl because they're implied by the bound `T: Bound`
6+
// on the implementor `Type`.
7+
8+
pub struct Type<T: Bound>(T);
9+
10+
// @has supertrait_bounds/struct.Type.html
11+
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
12+
// "impl<T> Send for Type<T>where T: Send,"
13+
14+
pub trait Bound: Copy + 'static {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ edition: 2021
2+
//@ check-pass
3+
//@ revisions: current next
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
5+
//@[next] compile-flags: -Znext-solver
6+
7+
#![feature(async_closure)]
8+
9+
fn constrain<T: async FnOnce()>(t: T) -> T {
10+
t
11+
}
12+
13+
fn call_once<T>(f: impl FnOnce() -> T) -> T {
14+
f()
15+
}
16+
17+
async fn async_call_once<T>(f: impl async FnOnce() -> T) -> T {
18+
f().await
19+
}
20+
21+
fn main() {
22+
let c = constrain(async || {});
23+
call_once(c);
24+
25+
let c = constrain(async || {});
26+
async_call_once(c);
27+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ edition: 2021
2+
//@ check-pass
3+
4+
#![feature(async_closure)]
5+
6+
pub struct Struct {
7+
pub path: String,
8+
}
9+
10+
// In `upvar.rs`, `truncate_capture_for_optimization` means that we don't actually
11+
// capture `&(*s.path)` here, but instead just `&(*s)`, but ONLY when the upvar is
12+
// immutable. This means that the assumption we have in `ByMoveBody` pass is wrong.
13+
pub fn test(s: &Struct) {
14+
let c = async move || { let path = &s.path; };
15+
}
16+
17+
fn main() {}
File renamed without changes.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
//@ aux-build:non_local_macro.rs
4+
//
5+
// To suggest any Cargo specific help/note rustc wants
6+
// the `CARGO_CRATE_NAME` env to be set, so we set it
7+
//@ rustc-env:CARGO_CRATE_NAME=non_local_def
8+
//
9+
// and since we specifically want to check the presence
10+
// of the `cargo update` suggestion we assert it here.
11+
//@ error-pattern: `cargo update -p non_local_macro`
12+
13+
extern crate non_local_macro;
14+
15+
struct LocalStruct;
16+
17+
non_local_macro::non_local_impl!(LocalStruct);
18+
//~^ WARN non-local `impl` definition
19+
20+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/cargo-update.rs:17:1
3+
|
4+
LL | non_local_macro::non_local_impl!(LocalStruct);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: move this `impl` block outside the of the current constant `_IMPL_DEBUG`
8+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
9+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
10+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
11+
= note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro`
12+
= note: `#[warn(non_local_definitions)]` on by default
13+
= note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
14+
15+
warning: 1 warning emitted
16+
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
//@ rustc-env:CARGO_CRATE_NAME=non_local_def
4+
5+
#![feature(inline_const)]
6+
7+
struct Test;
8+
9+
trait Uto {}
10+
const Z: () = {
11+
trait Uto1 {}
12+
13+
impl Uto1 for Test {} // the trait is local, don't lint
14+
15+
impl Uto for &Test {}
16+
//~^ WARN non-local `impl` definition
17+
};
18+
19+
trait Ano {}
20+
const _: () = {
21+
impl Ano for &Test {} // ignored since the parent is an anon-const
22+
};
23+
24+
trait Uto2 {}
25+
static A: u32 = {
26+
impl Uto2 for Test {}
27+
//~^ WARN non-local `impl` definition
28+
29+
1
30+
};
31+
32+
trait Uto3 {}
33+
const B: u32 = {
34+
impl Uto3 for Test {}
35+
//~^ WARN non-local `impl` definition
36+
37+
trait Uto4 {}
38+
impl Uto4 for Test {}
39+
40+
1
41+
};
42+
43+
trait Uto5 {}
44+
fn main() {
45+
impl Test {
46+
//~^ WARN non-local `impl` definition
47+
fn foo() {}
48+
}
49+
50+
51+
const {
52+
impl Test {
53+
//~^ WARN non-local `impl` definition
54+
fn hoo() {}
55+
}
56+
57+
1
58+
};
59+
60+
const _: u32 = {
61+
impl Test {
62+
//~^ WARN non-local `impl` definition
63+
fn foo2() {}
64+
}
65+
66+
1
67+
};
68+
}
69+
70+
trait Uto9 {}
71+
trait Uto10 {}
72+
const _: u32 = {
73+
let _a = || {
74+
impl Uto9 for Test {}
75+
//~^ WARN non-local `impl` definition
76+
77+
1
78+
};
79+
80+
type A = [u32; {
81+
impl Uto10 for Test {}
82+
//~^ WARN non-local `impl` definition
83+
84+
1
85+
}];
86+
87+
1
88+
};
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/consts.rs:15:5
3+
|
4+
LL | const Z: () = {
5+
| - help: use a const-anon item to suppress this lint: `_`
6+
...
7+
LL | impl Uto for &Test {}
8+
| ^^^^^^^^^^^^^^^^^^^^^
9+
|
10+
= help: move this `impl` block outside the of the current constant `Z`
11+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
12+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
13+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
14+
= note: `#[warn(non_local_definitions)]` on by default
15+
16+
warning: non-local `impl` definition, they should be avoided as they go against expectation
17+
--> $DIR/consts.rs:26:5
18+
|
19+
LL | impl Uto2 for Test {}
20+
| ^^^^^^^^^^^^^^^^^^^^^
21+
|
22+
= help: move this `impl` block outside the of the current static `A`
23+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
24+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
25+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
26+
27+
warning: non-local `impl` definition, they should be avoided as they go against expectation
28+
--> $DIR/consts.rs:34:5
29+
|
30+
LL | impl Uto3 for Test {}
31+
| ^^^^^^^^^^^^^^^^^^^^^
32+
|
33+
= help: move this `impl` block outside the of the current constant `B`
34+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
35+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
36+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
37+
38+
warning: non-local `impl` definition, they should be avoided as they go against expectation
39+
--> $DIR/consts.rs:45:5
40+
|
41+
LL | / impl Test {
42+
LL | |
43+
LL | | fn foo() {}
44+
LL | | }
45+
| |_____^
46+
|
47+
= help: move this `impl` block outside the of the current function `main`
48+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
49+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
50+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
51+
52+
warning: non-local `impl` definition, they should be avoided as they go against expectation
53+
--> $DIR/consts.rs:52:9
54+
|
55+
LL | / impl Test {
56+
LL | |
57+
LL | | fn hoo() {}
58+
LL | | }
59+
| |_________^
60+
|
61+
= help: move this `impl` block outside the of the current inline constant `<unnameable>` and up 2 bodies
62+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
63+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
64+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
65+
66+
warning: non-local `impl` definition, they should be avoided as they go against expectation
67+
--> $DIR/consts.rs:61:9
68+
|
69+
LL | / impl Test {
70+
LL | |
71+
LL | | fn foo2() {}
72+
LL | | }
73+
| |_________^
74+
|
75+
= help: move this `impl` block outside the of the current constant `_` and up 2 bodies
76+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
77+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
78+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
79+
80+
warning: non-local `impl` definition, they should be avoided as they go against expectation
81+
--> $DIR/consts.rs:74:9
82+
|
83+
LL | impl Uto9 for Test {}
84+
| ^^^^^^^^^^^^^^^^^^^^^
85+
|
86+
= help: move this `impl` block outside the of the current closure `<unnameable>` and up 2 bodies
87+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
88+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
89+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
90+
91+
warning: non-local `impl` definition, they should be avoided as they go against expectation
92+
--> $DIR/consts.rs:81:9
93+
|
94+
LL | impl Uto10 for Test {}
95+
| ^^^^^^^^^^^^^^^^^^^^^^
96+
|
97+
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
98+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
99+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
100+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
101+
102+
warning: 8 warnings emitted
103+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
struct Dog;
5+
6+
fn main() {
7+
impl PartialEq<()> for Dog {
8+
//~^ WARN non-local `impl` definition
9+
fn eq(&self, _: &()) -> bool {
10+
todo!()
11+
}
12+
}
13+
14+
impl PartialEq<()> for &Dog {
15+
//~^ WARN non-local `impl` definition
16+
fn eq(&self, _: &()) -> bool {
17+
todo!()
18+
}
19+
}
20+
21+
impl PartialEq<Dog> for () {
22+
//~^ WARN non-local `impl` definition
23+
fn eq(&self, _: &Dog) -> bool {
24+
todo!()
25+
}
26+
}
27+
28+
impl PartialEq<&Dog> for () {
29+
//~^ WARN non-local `impl` definition
30+
fn eq(&self, _: &&Dog) -> bool {
31+
todo!()
32+
}
33+
}
34+
35+
impl PartialEq<Dog> for &Dog {
36+
//~^ WARN non-local `impl` definition
37+
fn eq(&self, _: &Dog) -> bool {
38+
todo!()
39+
}
40+
}
41+
42+
impl PartialEq<&Dog> for &Dog {
43+
//~^ WARN non-local `impl` definition
44+
fn eq(&self, _: &&Dog) -> bool {
45+
todo!()
46+
}
47+
}
48+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/exhaustive-trait.rs:7:5
3+
|
4+
LL | / impl PartialEq<()> for Dog {
5+
LL | |
6+
LL | | fn eq(&self, _: &()) -> bool {
7+
LL | | todo!()
8+
LL | | }
9+
LL | | }
10+
| |_____^
11+
|
12+
= help: move this `impl` block outside the of the current function `main`
13+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
14+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
15+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
16+
= note: `#[warn(non_local_definitions)]` on by default
17+
18+
warning: non-local `impl` definition, they should be avoided as they go against expectation
19+
--> $DIR/exhaustive-trait.rs:14:5
20+
|
21+
LL | / impl PartialEq<()> for &Dog {
22+
LL | |
23+
LL | | fn eq(&self, _: &()) -> bool {
24+
LL | | todo!()
25+
LL | | }
26+
LL | | }
27+
| |_____^
28+
|
29+
= help: move this `impl` block outside the of the current function `main`
30+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
31+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
32+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
33+
34+
warning: non-local `impl` definition, they should be avoided as they go against expectation
35+
--> $DIR/exhaustive-trait.rs:21:5
36+
|
37+
LL | / impl PartialEq<Dog> for () {
38+
LL | |
39+
LL | | fn eq(&self, _: &Dog) -> bool {
40+
LL | | todo!()
41+
LL | | }
42+
LL | | }
43+
| |_____^
44+
|
45+
= help: move this `impl` block outside the of the current function `main`
46+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
47+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
48+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
49+
50+
warning: non-local `impl` definition, they should be avoided as they go against expectation
51+
--> $DIR/exhaustive-trait.rs:28:5
52+
|
53+
LL | / impl PartialEq<&Dog> for () {
54+
LL | |
55+
LL | | fn eq(&self, _: &&Dog) -> bool {
56+
LL | | todo!()
57+
LL | | }
58+
LL | | }
59+
| |_____^
60+
|
61+
= help: move this `impl` block outside the of the current function `main`
62+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
63+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
64+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
65+
66+
warning: non-local `impl` definition, they should be avoided as they go against expectation
67+
--> $DIR/exhaustive-trait.rs:35:5
68+
|
69+
LL | / impl PartialEq<Dog> for &Dog {
70+
LL | |
71+
LL | | fn eq(&self, _: &Dog) -> bool {
72+
LL | | todo!()
73+
LL | | }
74+
LL | | }
75+
| |_____^
76+
|
77+
= help: move this `impl` block outside the of the current function `main`
78+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
79+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
80+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
81+
82+
warning: non-local `impl` definition, they should be avoided as they go against expectation
83+
--> $DIR/exhaustive-trait.rs:42:5
84+
|
85+
LL | / impl PartialEq<&Dog> for &Dog {
86+
LL | |
87+
LL | | fn eq(&self, _: &&Dog) -> bool {
88+
LL | | todo!()
89+
LL | | }
90+
LL | | }
91+
| |_____^
92+
|
93+
= help: move this `impl` block outside the of the current function `main`
94+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
95+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
96+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
97+
98+
warning: 6 warnings emitted
99+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
use std::fmt::Display;
5+
6+
trait Trait {}
7+
struct Test;
8+
9+
fn main() {
10+
impl Test {
11+
//~^ WARN non-local `impl` definition
12+
fn foo() {}
13+
}
14+
15+
impl Display for Test {
16+
//~^ WARN non-local `impl` definition
17+
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18+
todo!()
19+
}
20+
}
21+
22+
impl dyn Trait {}
23+
//~^ WARN non-local `impl` definition
24+
25+
impl<T: Trait> Trait for Vec<T> { }
26+
//~^ WARN non-local `impl` definition
27+
28+
impl Trait for &dyn Trait {}
29+
//~^ WARN non-local `impl` definition
30+
31+
impl Trait for *mut Test {}
32+
//~^ WARN non-local `impl` definition
33+
34+
impl Trait for *mut [Test] {}
35+
//~^ WARN non-local `impl` definition
36+
37+
impl Trait for [Test; 8] {}
38+
//~^ WARN non-local `impl` definition
39+
40+
impl Trait for (Test,) {}
41+
//~^ WARN non-local `impl` definition
42+
43+
impl Trait for fn(Test) -> () {}
44+
//~^ WARN non-local `impl` definition
45+
46+
impl Trait for fn() -> Test {}
47+
//~^ WARN non-local `impl` definition
48+
49+
let _a = || {
50+
impl Trait for Test {}
51+
//~^ WARN non-local `impl` definition
52+
53+
1
54+
};
55+
56+
struct InsideMain;
57+
58+
impl Trait for *mut InsideMain {}
59+
//~^ WARN non-local `impl` definition
60+
impl Trait for *mut [InsideMain] {}
61+
//~^ WARN non-local `impl` definition
62+
impl Trait for [InsideMain; 8] {}
63+
//~^ WARN non-local `impl` definition
64+
impl Trait for (InsideMain,) {}
65+
//~^ WARN non-local `impl` definition
66+
impl Trait for fn(InsideMain) -> () {}
67+
//~^ WARN non-local `impl` definition
68+
impl Trait for fn() -> InsideMain {}
69+
//~^ WARN non-local `impl` definition
70+
71+
fn inside_inside() {
72+
impl Display for InsideMain {
73+
//~^ WARN non-local `impl` definition
74+
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75+
todo!()
76+
}
77+
}
78+
79+
impl InsideMain {
80+
//~^ WARN non-local `impl` definition
81+
fn bar() {}
82+
}
83+
}
84+
}

‎tests/ui/lint/non-local-defs/exhaustive.stderr‎

Lines changed: 239 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
#![feature(inline_const)]
5+
6+
struct Cat;
7+
struct Wrap<T>(T);
8+
9+
fn main() {
10+
impl From<Cat> for () {
11+
//~^ WARN non-local `impl` definition
12+
fn from(_: Cat) -> () {
13+
todo!()
14+
}
15+
}
16+
17+
#[derive(Debug)]
18+
struct Elephant;
19+
20+
impl From<Wrap<Wrap<Elephant>>> for () {
21+
//~^ WARN non-local `impl` definition
22+
fn from(_: Wrap<Wrap<Elephant>>) -> Self {
23+
todo!()
24+
}
25+
}
26+
}
27+
28+
pub trait StillNonLocal {}
29+
30+
impl StillNonLocal for &str {}
31+
32+
fn only_global() {
33+
struct Foo;
34+
impl StillNonLocal for &Foo {}
35+
//~^ WARN non-local `impl` definition
36+
}
37+
38+
struct GlobalSameFunction;
39+
40+
fn same_function() {
41+
struct Local1(GlobalSameFunction);
42+
impl From<Local1> for GlobalSameFunction {
43+
//~^ WARN non-local `impl` definition
44+
fn from(x: Local1) -> GlobalSameFunction {
45+
x.0
46+
}
47+
}
48+
49+
struct Local2(GlobalSameFunction);
50+
impl From<Local2> for GlobalSameFunction {
51+
//~^ WARN non-local `impl` definition
52+
fn from(x: Local2) -> GlobalSameFunction {
53+
x.0
54+
}
55+
}
56+
}
57+
58+
struct GlobalDifferentFunction;
59+
60+
fn diff_function_1() {
61+
struct Local(GlobalDifferentFunction);
62+
63+
impl From<Local> for GlobalDifferentFunction {
64+
// FIXME(Urgau): Should warn but doesn't since we currently consider
65+
// the other impl to be "global", but that's not the case for the type-system
66+
fn from(x: Local) -> GlobalDifferentFunction {
67+
x.0
68+
}
69+
}
70+
}
71+
72+
fn diff_function_2() {
73+
struct Local(GlobalDifferentFunction);
74+
75+
impl From<Local> for GlobalDifferentFunction {
76+
// FIXME(Urgau): Should warn but doesn't since we currently consider
77+
// the other impl to be "global", but that's not the case for the type-system
78+
fn from(x: Local) -> GlobalDifferentFunction {
79+
x.0
80+
}
81+
}
82+
}
83+
84+
// https://github.com/rust-lang/rust/issues/121621#issuecomment-1976826895
85+
fn commonly_reported() {
86+
struct Local(u8);
87+
impl From<Local> for u8 {
88+
fn from(x: Local) -> u8 {
89+
x.0
90+
}
91+
}
92+
}
93+
94+
// https://github.com/rust-lang/rust/issues/121621#issue-2153187542
95+
pub trait Serde {}
96+
97+
impl Serde for &[u8] {}
98+
impl Serde for &str {}
99+
100+
fn serde() {
101+
struct Thing;
102+
impl Serde for &Thing {}
103+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/from-local-for-global.rs:10:5
3+
|
4+
LL | / impl From<Cat> for () {
5+
LL | |
6+
LL | | fn from(_: Cat) -> () {
7+
LL | | todo!()
8+
LL | | }
9+
LL | | }
10+
| |_____^
11+
|
12+
= help: move this `impl` block outside the of the current function `main`
13+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
14+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
15+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
16+
= note: `#[warn(non_local_definitions)]` on by default
17+
18+
warning: non-local `impl` definition, they should be avoided as they go against expectation
19+
--> $DIR/from-local-for-global.rs:20:5
20+
|
21+
LL | / impl From<Wrap<Wrap<Elephant>>> for () {
22+
LL | |
23+
LL | | fn from(_: Wrap<Wrap<Elephant>>) -> Self {
24+
LL | | todo!()
25+
LL | | }
26+
LL | | }
27+
| |_____^
28+
|
29+
= help: move this `impl` block outside the of the current function `main`
30+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
31+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
32+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
33+
34+
warning: non-local `impl` definition, they should be avoided as they go against expectation
35+
--> $DIR/from-local-for-global.rs:34:5
36+
|
37+
LL | impl StillNonLocal for &Foo {}
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
= help: move this `impl` block outside the of the current function `only_global`
41+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
42+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
43+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
44+
45+
warning: non-local `impl` definition, they should be avoided as they go against expectation
46+
--> $DIR/from-local-for-global.rs:42:5
47+
|
48+
LL | / impl From<Local1> for GlobalSameFunction {
49+
LL | |
50+
LL | | fn from(x: Local1) -> GlobalSameFunction {
51+
LL | | x.0
52+
LL | | }
53+
LL | | }
54+
| |_____^
55+
|
56+
= help: move this `impl` block outside the of the current function `same_function`
57+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
58+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
59+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
60+
61+
warning: non-local `impl` definition, they should be avoided as they go against expectation
62+
--> $DIR/from-local-for-global.rs:50:5
63+
|
64+
LL | / impl From<Local2> for GlobalSameFunction {
65+
LL | |
66+
LL | | fn from(x: Local2) -> GlobalSameFunction {
67+
LL | | x.0
68+
LL | | }
69+
LL | | }
70+
| |_____^
71+
|
72+
= help: move this `impl` block outside the of the current function `same_function`
73+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
74+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
75+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
76+
77+
warning: 5 warnings emitted
78+
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
trait Global {}
5+
6+
fn main() {
7+
trait Local {};
8+
9+
impl<T: Local> Global for Vec<T> { }
10+
//~^ WARN non-local `impl` definition
11+
}
12+
13+
trait Uto7 {}
14+
trait Uto8 {}
15+
16+
struct Test;
17+
18+
fn bad() {
19+
struct Local;
20+
impl Uto7 for Test where Local: std::any::Any {}
21+
//~^ WARN non-local `impl` definition
22+
23+
impl<T> Uto8 for T {}
24+
//~^ WARN non-local `impl` definition
25+
}
26+
27+
struct UwU<T>(T);
28+
29+
fn fun() {
30+
#[derive(Debug)]
31+
struct OwO;
32+
impl Default for UwU<OwO> {
33+
//~^ WARN non-local `impl` definition
34+
fn default() -> Self {
35+
UwU(OwO)
36+
}
37+
}
38+
}
39+
40+
fn meow() {
41+
#[derive(Debug)]
42+
struct Cat;
43+
impl AsRef<Cat> for () {
44+
//~^ WARN non-local `impl` definition
45+
fn as_ref(&self) -> &Cat { &Cat }
46+
}
47+
}
48+
49+
struct G;
50+
51+
fn fun2() {
52+
#[derive(Debug, Default)]
53+
struct B;
54+
impl PartialEq<B> for G {
55+
//~^ WARN non-local `impl` definition
56+
fn eq(&self, _: &B) -> bool {
57+
true
58+
}
59+
}
60+
}
61+
62+
struct Wrap<T>(T);
63+
64+
impl Wrap<Wrap<Wrap<()>>> {}
65+
66+
fn rawr() {
67+
struct Lion;
68+
69+
impl From<Wrap<Wrap<Lion>>> for () {
70+
//~^ WARN non-local `impl` definition
71+
fn from(_: Wrap<Wrap<Lion>>) -> Self {
72+
todo!()
73+
}
74+
}
75+
76+
impl From<()> for Wrap<Lion> {
77+
//~^ WARN non-local `impl` definition
78+
fn from(_: ()) -> Self {
79+
todo!()
80+
}
81+
}
82+
}
83+
84+
fn side_effects() {
85+
dbg!(().as_ref()); // prints `Cat`
86+
dbg!(UwU::default().0);
87+
let _ = G::eq(&G, dbg!(&<_>::default()));
88+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/generics.rs:9:5
3+
|
4+
LL | impl<T: Local> Global for Vec<T> { }
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: move this `impl` block outside the of the current function `main`
8+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
9+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
10+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
11+
= note: `#[warn(non_local_definitions)]` on by default
12+
13+
warning: non-local `impl` definition, they should be avoided as they go against expectation
14+
--> $DIR/generics.rs:20:5
15+
|
16+
LL | impl Uto7 for Test where Local: std::any::Any {}
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
= help: move this `impl` block outside the of the current function `bad`
20+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
21+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
22+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
23+
24+
warning: non-local `impl` definition, they should be avoided as they go against expectation
25+
--> $DIR/generics.rs:23:5
26+
|
27+
LL | impl<T> Uto8 for T {}
28+
| ^^^^^^^^^^^^^^^^^^^^^
29+
|
30+
= help: move this `impl` block outside the of the current function `bad`
31+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
32+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
33+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
34+
35+
warning: non-local `impl` definition, they should be avoided as they go against expectation
36+
--> $DIR/generics.rs:32:5
37+
|
38+
LL | / impl Default for UwU<OwO> {
39+
LL | |
40+
LL | | fn default() -> Self {
41+
LL | | UwU(OwO)
42+
LL | | }
43+
LL | | }
44+
| |_____^
45+
|
46+
= help: move this `impl` block outside the of the current function `fun`
47+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
48+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
49+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
50+
51+
warning: non-local `impl` definition, they should be avoided as they go against expectation
52+
--> $DIR/generics.rs:43:5
53+
|
54+
LL | / impl AsRef<Cat> for () {
55+
LL | |
56+
LL | | fn as_ref(&self) -> &Cat { &Cat }
57+
LL | | }
58+
| |_____^
59+
|
60+
= help: move this `impl` block outside the of the current function `meow`
61+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
62+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
63+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
64+
65+
warning: non-local `impl` definition, they should be avoided as they go against expectation
66+
--> $DIR/generics.rs:54:5
67+
|
68+
LL | / impl PartialEq<B> for G {
69+
LL | |
70+
LL | | fn eq(&self, _: &B) -> bool {
71+
LL | | true
72+
LL | | }
73+
LL | | }
74+
| |_____^
75+
|
76+
= help: move this `impl` block outside the of the current function `fun2`
77+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
78+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
79+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
80+
81+
warning: non-local `impl` definition, they should be avoided as they go against expectation
82+
--> $DIR/generics.rs:69:5
83+
|
84+
LL | / impl From<Wrap<Wrap<Lion>>> for () {
85+
LL | |
86+
LL | | fn from(_: Wrap<Wrap<Lion>>) -> Self {
87+
LL | | todo!()
88+
LL | | }
89+
LL | | }
90+
| |_____^
91+
|
92+
= help: move this `impl` block outside the of the current function `rawr`
93+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
94+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
95+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
96+
97+
warning: non-local `impl` definition, they should be avoided as they go against expectation
98+
--> $DIR/generics.rs:76:5
99+
|
100+
LL | / impl From<()> for Wrap<Lion> {
101+
LL | |
102+
LL | | fn from(_: ()) -> Self {
103+
LL | | todo!()
104+
LL | | }
105+
LL | | }
106+
| |_____^
107+
|
108+
= help: move this `impl` block outside the of the current function `rawr`
109+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
110+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
111+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
112+
113+
warning: 8 warnings emitted
114+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
macro_rules! m {
5+
() => {
6+
trait MacroTrait {}
7+
struct OutsideStruct;
8+
fn my_func() {
9+
impl MacroTrait for OutsideStruct {}
10+
//~^ WARN non-local `impl` definition
11+
}
12+
}
13+
}
14+
15+
m!();
16+
17+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/inside-macro_rules.rs:9:13
3+
|
4+
LL | impl MacroTrait for OutsideStruct {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
...
7+
LL | m!();
8+
| ---- in this macro invocation
9+
|
10+
= help: move this `impl` block outside the of the current function `my_func`
11+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
12+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
13+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
14+
= note: `#[warn(non_local_definitions)]` on by default
15+
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
17+
warning: 1 warning emitted
18+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
use std::fmt::Debug;
5+
6+
trait GlobalTrait {}
7+
8+
fn main() {
9+
struct InsideMain;
10+
11+
impl InsideMain {
12+
fn foo() {}
13+
}
14+
15+
impl GlobalTrait for InsideMain {}
16+
17+
impl Debug for InsideMain {
18+
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19+
todo!()
20+
}
21+
}
22+
23+
impl PartialEq<()> for InsideMain {
24+
fn eq(&self, _: &()) -> bool {
25+
todo!()
26+
}
27+
}
28+
}
29+
30+
fn dyn_weirdness() {
31+
trait LocalTrait {}
32+
impl dyn LocalTrait {}
33+
impl GlobalTrait for dyn LocalTrait {}
34+
}
35+
36+
struct Test;
37+
mod do_not_lint_mod {
38+
pub trait Tait {}
39+
40+
impl super::Test {
41+
fn hugo() {}
42+
}
43+
44+
impl Tait for super::Test {}
45+
}
46+
47+
fn bitflags() {
48+
struct Flags;
49+
50+
const _: () = {
51+
impl Flags {}
52+
};
53+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
//@ aux-build:non_local_macro.rs
4+
//@ rustc-env:CARGO_CRATE_NAME=non_local_def
5+
6+
extern crate non_local_macro;
7+
8+
const B: u32 = {
9+
#[macro_export]
10+
macro_rules! m0 { () => { } };
11+
//~^ WARN non-local `macro_rules!` definition
12+
13+
1
14+
};
15+
16+
non_local_macro::non_local_macro_rules!(my_macro);
17+
//~^ WARN non-local `macro_rules!` definition
18+
19+
fn main() {
20+
#[macro_export]
21+
macro_rules! m { () => { } };
22+
//~^ WARN non-local `macro_rules!` definition
23+
24+
struct InsideMain;
25+
26+
impl InsideMain {
27+
fn bar() {
28+
#[macro_export]
29+
macro_rules! m2 { () => { } };
30+
//~^ WARN non-local `macro_rules!` definition
31+
}
32+
}
33+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
2+
--> $DIR/macro_rules.rs:10:5
3+
|
4+
LL | macro_rules! m0 { () => { } };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `B`
8+
= note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
9+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
10+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
11+
= note: `#[warn(non_local_definitions)]` on by default
12+
13+
warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
14+
--> $DIR/macro_rules.rs:16:1
15+
|
16+
LL | non_local_macro::non_local_macro_rules!(my_macro);
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
= help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `_MACRO_EXPORT`
20+
= note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
21+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
22+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
23+
= note: the macro `non_local_macro::non_local_macro_rules` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro`
24+
= note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
25+
26+
warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
27+
--> $DIR/macro_rules.rs:21:5
28+
|
29+
LL | macro_rules! m { () => { } };
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main`
33+
= note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
34+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
35+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
36+
37+
warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
38+
--> $DIR/macro_rules.rs:29:13
39+
|
40+
LL | macro_rules! m2 { () => { } };
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
|
43+
= help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current associated function `bar` and up 2 bodies
44+
= note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
45+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
46+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
47+
48+
warning: 4 warnings emitted
49+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//@ check-pass
2+
//@ edition:2021
3+
4+
trait Uto {}
5+
struct Test;
6+
7+
type A = [u32; {
8+
impl Uto for *mut Test {}
9+
//~^ WARN non-local `impl` definition
10+
11+
1
12+
}];
13+
14+
enum Enum {
15+
Discr = {
16+
impl Uto for Test {}
17+
//~^ WARN non-local `impl` definition
18+
19+
1
20+
}
21+
}
22+
23+
fn main() {
24+
let _array = [0i32; {
25+
impl Test {
26+
//~^ WARN non-local `impl` definition
27+
fn bar() {}
28+
}
29+
30+
1
31+
}];
32+
33+
type A = [u32; {
34+
impl Uto for &Test {}
35+
//~^ WARN non-local `impl` definition
36+
37+
1
38+
}];
39+
40+
fn a(_: [u32; {
41+
impl Uto for &(Test,) {}
42+
//~^ WARN non-local `impl` definition
43+
44+
1
45+
}]) {}
46+
47+
fn b() -> [u32; {
48+
impl Uto for &(Test,Test) {}
49+
//~^ WARN non-local `impl` definition
50+
51+
1
52+
}] { todo!() }
53+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
warning: non-local `impl` definition, they should be avoided as they go against expectation
2+
--> $DIR/weird-exprs.rs:8:5
3+
|
4+
LL | impl Uto for *mut Test {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: move this `impl` block outside the of the current constant expression `<unnameable>`
8+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
9+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
10+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
11+
= note: `#[warn(non_local_definitions)]` on by default
12+
13+
warning: non-local `impl` definition, they should be avoided as they go against expectation
14+
--> $DIR/weird-exprs.rs:16:9
15+
|
16+
LL | impl Uto for Test {}
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
|
19+
= help: move this `impl` block outside the of the current constant expression `<unnameable>`
20+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
21+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
22+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
23+
24+
warning: non-local `impl` definition, they should be avoided as they go against expectation
25+
--> $DIR/weird-exprs.rs:25:9
26+
|
27+
LL | / impl Test {
28+
LL | |
29+
LL | | fn bar() {}
30+
LL | | }
31+
| |_________^
32+
|
33+
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
34+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
35+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
36+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
37+
38+
warning: non-local `impl` definition, they should be avoided as they go against expectation
39+
--> $DIR/weird-exprs.rs:34:9
40+
|
41+
LL | impl Uto for &Test {}
42+
| ^^^^^^^^^^^^^^^^^^^^^
43+
|
44+
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
45+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
46+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
47+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
48+
49+
warning: non-local `impl` definition, they should be avoided as they go against expectation
50+
--> $DIR/weird-exprs.rs:41:9
51+
|
52+
LL | impl Uto for &(Test,) {}
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^
54+
|
55+
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
56+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
57+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
58+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
59+
60+
warning: non-local `impl` definition, they should be avoided as they go against expectation
61+
--> $DIR/weird-exprs.rs:48:9
62+
|
63+
LL | impl Uto for &(Test,Test) {}
64+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65+
|
66+
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
67+
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
68+
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
69+
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
70+
71+
warning: 6 warnings emitted
72+

‎tests/ui/lint/non_local_definitions.rs‎

Lines changed: 0 additions & 491 deletions
This file was deleted.

‎tests/ui/lint/non_local_definitions.stderr‎

Lines changed: 0 additions & 705 deletions
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.