Skip to content

Commit

Permalink
Rollup merge of #115924 - compiler-errors:non-exhaustive-1-zst, r=Ral…
Browse files Browse the repository at this point in the history
…fJung

Don't complain on a single non-exhaustive 1-ZST

r? RalfJung, though you mentioned being busy, so feel free to reassign.

This doesn't actually attempt to make the diagnostic better, so when we have two non-exhaustive 1-ZSTs in a struct, we still just point to one. 🤷

Fixes #115922
  • Loading branch information
GuillaumeGomez committed Sep 19, 2023
2 parents 6cfc6a8 + fd36553 commit f1edecf
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
48 changes: 29 additions & 19 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,25 +1201,35 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
);
return;
}
for (span, _trivial, non_exhaustive) in field_infos {
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
span,
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
|lint| {
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
} else {
"contains private fields"
};
let field_ty = tcx.def_path_str_with_args(def_id, args);
lint
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become non-zero-sized in the future."))
},
)
let mut prev_non_exhaustive_1zst = false;
for (span, _trivial, non_exhaustive_1zst) in field_infos {
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst {
// If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
// Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
if non_trivial_count > 0 || prev_non_exhaustive_1zst {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
span,
"zero-sized fields in `repr(transparent)` cannot \
contain external non-exhaustive types",
|lint| {
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
} else {
"contains private fields"
};
let field_ty = tcx.def_path_str_with_args(def_id, args);
lint.note(format!(
"this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become \
non-zero-sized in the future."
))
},
)
} else {
prev_non_exhaustive_1zst = true;
}
}
}
}
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/repr/repr-transparent-non-exhaustive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,44 @@ pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler

#[repr(transparent)]
pub struct T17(NonExhaustive, Sized);
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler

#[repr(transparent)]
pub struct T18(NonExhaustive, NonExhaustive);
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler

#[repr(transparent)]
pub struct T19(NonExhaustive, Private);
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler

#[repr(transparent)]
pub struct T19Flipped(Private, NonExhaustive);
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler

#[repr(transparent)]
pub struct T20(NonExhaustive);
// Okay, since it's the only field.

#[repr(transparent)]
pub struct T21(NonExhaustive, InternalNonExhaustive);
// Okay, since there's only 1 foreign non-exhaustive type.

#[repr(transparent)]
pub struct T21Flipped(InternalNonExhaustive, NonExhaustive);
// Okay, since there's only 1 foreign non-exhaustive type.

#[repr(transparent)]
pub struct T22(NonExhaustive, InternalPrivate);
// Okay, since there's only 1 foreign non-exhaustive type.

#[repr(transparent)]
pub struct T22Flipped(InternalPrivate, NonExhaustive);
// Okay, since there's only 1 foreign non-exhaustive type.

fn main() {}
42 changes: 41 additions & 1 deletion tests/ui/repr/repr-transparent-non-exhaustive.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,45 @@ LL | pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.

error: aborting due to 12 previous errors
error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:97:16
|
LL | pub struct T17(NonExhaustive, Sized);
| ^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.

error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:102:31
|
LL | pub struct T18(NonExhaustive, NonExhaustive);
| ^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.

error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:107:31
|
LL | pub struct T19(NonExhaustive, Private);
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.

error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:112:32
|
LL | pub struct T19Flipped(Private, NonExhaustive);
| ^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.

error: aborting due to 16 previous errors

0 comments on commit f1edecf

Please sign in to comment.