Skip to content

Commit 115fd00

Browse files
committed
Auto merge of #139007 - jhpratt:rollup-rn0zaw7, r=jhpratt
Rollup of 10 pull requests Successful merges: - #136083 (Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc) - #138344 (Enable `reliable_f16_math` on x86) - #138624 (Add mipsel maintainer) - #138935 (Update wg-prio triagebot config) - #138946 (Un-bury chapters from the chapter list in rustc book) - #138964 (Implement lint against using Interner and InferCtxtLike in random compiler crates) - #138977 (Don't deaggregate InvocationParent just to reaggregate it again) - #138980 (Collect items referenced from var_debug_info) - #138985 (Use the correct binder scope for elided lifetimes in assoc consts) - #138987 (Always emit `native-static-libs` note, even if it is empty) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1644cb0 + 88bb2fb commit 115fd00

File tree

77 files changed

+972
-249
lines changed

Some content is hidden

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

77 files changed

+972
-249
lines changed

compiler/rustc_codegen_cranelift/example/example.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(no_core, unboxed_closures)]
22
#![no_core]
3-
#![allow(dead_code)]
3+
#![allow(dead_code, unnecessary_transmutes)]
44

55
extern crate mini_core;
66

compiler/rustc_codegen_gcc/example/example.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(no_core, unboxed_closures)]
22
#![no_core]
3-
#![allow(dead_code)]
3+
#![allow(dead_code, unnecessary_transmutes)]
44

55
extern crate mini_core;
66

@@ -11,11 +11,7 @@ fn abc(a: u8) -> u8 {
1111
}
1212

1313
fn bcd(b: bool, a: u8) -> u8 {
14-
if b {
15-
a * 2
16-
} else {
17-
a * 3
18-
}
14+
if b { a * 2 } else { a * 3 }
1915
}
2016

2117
fn call() {

compiler/rustc_codegen_ssa/src/back/link.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -1560,17 +1560,13 @@ fn print_native_static_libs(
15601560
match out {
15611561
OutFileName::Real(path) => {
15621562
out.overwrite(&lib_args.join(" "), sess);
1563-
if !lib_args.is_empty() {
1564-
sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
1565-
}
1563+
sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
15661564
}
15671565
OutFileName::Stdout => {
1568-
if !lib_args.is_empty() {
1569-
sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
1570-
// Prefix for greppability
1571-
// Note: This must not be translated as tools are allowed to depend on this exact string.
1572-
sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
1573-
}
1566+
sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
1567+
// Prefix for greppability
1568+
// Note: This must not be translated as tools are allowed to depend on this exact string.
1569+
sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
15741570
}
15751571
}
15761572
}

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ lint_tykind_kind = usage of `ty::TyKind::<kind>`
799799
lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
800800
.note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
801801
802+
lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
803+
.note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
804+
802805
lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
803806
.label = argument has type `{$arg_ty}`
804807
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value

compiler/rustc_lint/src/internal.rs

+86-42
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
22
//! Clippy.
33
4-
use rustc_ast as ast;
4+
use rustc_hir::HirId;
55
use rustc_hir::def::Res;
66
use rustc_hir::def_id::DefId;
7-
use rustc_hir::{
8-
AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
9-
PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
10-
};
117
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
128
use rustc_session::{declare_lint_pass, declare_tool_lint};
139
use rustc_span::hygiene::{ExpnKind, MacroKind};
1410
use rustc_span::{Span, sym};
1511
use tracing::debug;
12+
use {rustc_ast as ast, rustc_hir as hir};
1613

1714
use crate::lints::{
1815
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
1916
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
2017
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
21-
UntranslatableDiag,
18+
TypeIrTraitUsage, UntranslatableDiag,
2219
};
2320
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
2421

@@ -37,9 +34,12 @@ declare_tool_lint! {
3734
declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
3835

3936
impl LateLintPass<'_> for DefaultHashTypes {
40-
fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
37+
fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
4138
let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
42-
if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) {
39+
if matches!(
40+
cx.tcx.hir_node(hir_id),
41+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
42+
) {
4343
// Don't lint imports, only actual usages.
4444
return;
4545
}
@@ -60,10 +60,10 @@ impl LateLintPass<'_> for DefaultHashTypes {
6060
/// get the `DefId` and `GenericArgsRef` of the function.
6161
fn typeck_results_of_method_fn<'tcx>(
6262
cx: &LateContext<'tcx>,
63-
expr: &Expr<'_>,
63+
expr: &hir::Expr<'_>,
6464
) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
6565
match expr.kind {
66-
ExprKind::MethodCall(segment, ..)
66+
hir::ExprKind::MethodCall(segment, ..)
6767
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
6868
{
6969
Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
@@ -102,7 +102,7 @@ declare_tool_lint! {
102102
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
103103

104104
impl LateLintPass<'_> for QueryStability {
105-
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
105+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
106106
let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
107107
if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
108108
{
@@ -164,21 +164,25 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
164164
}
165165
}
166166

167-
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) {
167+
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
168168
match &ty.kind {
169-
TyKind::Path(QPath::Resolved(_, path)) => {
169+
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
170170
if lint_ty_kind_usage(cx, &path.res) {
171171
let span = match cx.tcx.parent_hir_node(ty.hir_id) {
172-
Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. })
173-
| Node::Pat(Pat {
174-
kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
172+
hir::Node::PatExpr(hir::PatExpr {
173+
kind: hir::PatExprKind::Path(qpath),
174+
..
175+
})
176+
| hir::Node::Pat(hir::Pat {
177+
kind:
178+
hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
175179
..
176180
})
177-
| Node::Expr(
178-
Expr { kind: ExprKind::Path(qpath), .. }
179-
| &Expr { kind: ExprKind::Struct(qpath, ..), .. },
181+
| hir::Node::Expr(
182+
hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
183+
| &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
180184
) => {
181-
if let QPath::TypeRelative(qpath_ty, ..) = qpath
185+
if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
182186
&& qpath_ty.hir_id == ty.hir_id
183187
{
184188
Some(path.span)
@@ -223,7 +227,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
223227
}
224228
}
225229

226-
fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
230+
fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
227231
match &path.res {
228232
Res::Def(_, def_id) => {
229233
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) {
@@ -244,13 +248,17 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
244248
None
245249
}
246250

247-
fn gen_args(segment: &PathSegment<'_>) -> String {
251+
fn gen_args(segment: &hir::PathSegment<'_>) -> String {
248252
if let Some(args) = &segment.args {
249253
let lifetimes = args
250254
.args
251255
.iter()
252256
.filter_map(|arg| {
253-
if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
257+
if let hir::GenericArg::Lifetime(lt) = arg {
258+
Some(lt.ident.to_string())
259+
} else {
260+
None
261+
}
254262
})
255263
.collect::<Vec<_>>();
256264

@@ -272,7 +280,7 @@ declare_tool_lint! {
272280
}
273281

274282
declare_tool_lint! {
275-
/// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`.
283+
/// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
276284
///
277285
/// This module should only be used within the trait solver.
278286
pub rustc::USAGE_OF_TYPE_IR_INHERENT,
@@ -281,10 +289,43 @@ declare_tool_lint! {
281289
report_in_external_macro: true
282290
}
283291

284-
declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]);
292+
declare_tool_lint! {
293+
/// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
294+
/// or `rustc_infer::InferCtxtLike`.
295+
///
296+
/// Methods of this trait should only be used within the type system abstraction layer,
297+
/// and in the generic next trait solver implementation. Look for an analogously named
298+
/// method on `TyCtxt` or `InferCtxt` (respectively).
299+
pub rustc::USAGE_OF_TYPE_IR_TRAITS,
300+
Allow,
301+
"usage `rustc_type_ir`-specific abstraction traits outside of trait system",
302+
report_in_external_macro: true
303+
}
304+
305+
declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
285306

286307
impl<'tcx> LateLintPass<'tcx> for TypeIr {
287-
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
308+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
309+
let res_def_id = match expr.kind {
310+
hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
311+
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
312+
cx.typeck_results().type_dependent_def_id(expr.hir_id)
313+
}
314+
_ => return,
315+
};
316+
let Some(res_def_id) = res_def_id else {
317+
return;
318+
};
319+
if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
320+
&& let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
321+
&& (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
322+
| cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
323+
{
324+
cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
325+
}
326+
}
327+
328+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
288329
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
289330

290331
let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
@@ -394,23 +435,23 @@ declare_tool_lint! {
394435
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
395436

396437
impl LateLintPass<'_> for Diagnostics {
397-
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
398-
let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| {
438+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
439+
let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
399440
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
400441
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
401442
result
402443
};
403444
// Only check function calls and method calls.
404445
let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
405-
ExprKind::Call(callee, args) => {
446+
hir::ExprKind::Call(callee, args) => {
406447
match cx.typeck_results().node_type(callee.hir_id).kind() {
407448
&ty::FnDef(def_id, fn_gen_args) => {
408449
(callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
409450
}
410451
_ => return, // occurs for fns passed as args
411452
}
412453
}
413-
ExprKind::MethodCall(_segment, _recv, args, _span) => {
454+
hir::ExprKind::MethodCall(_segment, _recv, args, _span) => {
414455
let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
415456
else {
416457
return;
@@ -514,8 +555,8 @@ impl Diagnostics {
514555
let mut is_inside_appropriate_impl = false;
515556
for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
516557
debug!(?parent);
517-
if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
518-
&& let Impl { of_trait: Some(of_trait), .. } = impl_
558+
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
559+
&& let hir::Impl { of_trait: Some(of_trait), .. } = impl_
519560
&& let Some(def_id) = of_trait.trait_def_id()
520561
&& let Some(name) = cx.tcx.get_diagnostic_name(def_id)
521562
&& matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
@@ -543,8 +584,8 @@ declare_tool_lint! {
543584
declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
544585

545586
impl LateLintPass<'_> for BadOptAccess {
546-
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
547-
let ExprKind::Field(base, target) = expr.kind else { return };
587+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
588+
let hir::ExprKind::Field(base, target) = expr.kind else { return };
548589
let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
549590
// Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
550591
// avoided.
@@ -581,9 +622,12 @@ declare_tool_lint! {
581622
declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
582623

583624
impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
584-
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
585-
if let ExprKind::Binary(BinOp { node: BinOpKind::Eq | BinOpKind::Ne, .. }, lhs, rhs) =
586-
expr.kind
625+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
626+
if let hir::ExprKind::Binary(
627+
hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. },
628+
lhs,
629+
rhs,
630+
) = expr.kind
587631
{
588632
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
589633
cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
@@ -592,9 +636,9 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
592636
}
593637
}
594638

595-
fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
639+
fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
596640
match &expr.kind {
597-
ExprKind::MethodCall(..) => cx
641+
hir::ExprKind::MethodCall(..) => cx
598642
.typeck_results()
599643
.type_dependent_def_id(expr.hir_id)
600644
.is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
@@ -617,11 +661,11 @@ declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
617661

618662
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
619663
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
620-
if let ExprKind::Call(path, [arg]) = expr.kind
621-
&& let ExprKind::Path(ref qpath) = path.kind
664+
if let hir::ExprKind::Call(path, [arg]) = expr.kind
665+
&& let hir::ExprKind::Path(ref qpath) = path.kind
622666
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
623667
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
624-
&& let ExprKind::Lit(kind) = arg.kind
668+
&& let hir::ExprKind::Lit(kind) = arg.kind
625669
&& let rustc_ast::LitKind::Str(_, _) = kind.node
626670
{
627671
cx.emit_span_lint(

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ fn register_internals(store: &mut LintStore) {
645645
LintId::of(USAGE_OF_QUALIFIED_TY),
646646
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
647647
LintId::of(USAGE_OF_TYPE_IR_INHERENT),
648+
LintId::of(USAGE_OF_TYPE_IR_TRAITS),
648649
LintId::of(BAD_OPT_ACCESS),
649650
LintId::of(SPAN_USE_EQ_CTXT),
650651
],

compiler/rustc_lint/src/lints.rs

+5
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,11 @@ pub(crate) struct TyQualified {
943943
#[note]
944944
pub(crate) struct TypeIrInherentUsage;
945945

946+
#[derive(LintDiagnostic)]
947+
#[diag(lint_type_ir_trait_usage)]
948+
#[note]
949+
pub(crate) struct TypeIrTraitUsage;
950+
946951
#[derive(LintDiagnostic)]
947952
#[diag(lint_non_glob_import_type_ir_inherent)]
948953
pub(crate) struct NonGlobImportTypeIrInherent {

compiler/rustc_lint_defs/src/builtin.rs

+25
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ declare_lint_pass! {
119119
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
120120
UNNAMEABLE_TEST_ITEMS,
121121
UNNAMEABLE_TYPES,
122+
UNNECESSARY_TRANSMUTES,
122123
UNREACHABLE_CODE,
123124
UNREACHABLE_PATTERNS,
124125
UNSAFE_ATTR_OUTSIDE_UNSAFE,
@@ -4944,6 +4945,30 @@ declare_lint! {
49444945
"detects pointer to integer transmutes in const functions and associated constants",
49454946
}
49464947

4948+
declare_lint! {
4949+
/// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
4950+
///
4951+
/// ### Example
4952+
///
4953+
/// ```rust
4954+
/// fn bytes_at_home(x: [u8; 4]) -> u32 {
4955+
/// unsafe { std::mem::transmute(x) }
4956+
/// }
4957+
/// ```
4958+
///
4959+
/// {{produces}}
4960+
///
4961+
/// ### Explanation
4962+
///
4963+
/// Using an explicit method is preferable over calls to
4964+
/// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
4965+
/// they more clearly communicate the intent, are easier to review, and
4966+
/// are less likely to accidentally result in unsoundness.
4967+
pub UNNECESSARY_TRANSMUTES,
4968+
Warn,
4969+
"detects transmutes that are shadowed by std methods"
4970+
}
4971+
49474972
declare_lint! {
49484973
/// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location,
49494974
/// that runs a custom `Drop` destructor.

0 commit comments

Comments
 (0)