Skip to content

Commit 9857284

Browse files
committed
Auto merge of rust-lang#135715 - matthiaskrgr:rollup-9a18sxj, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang#135641 ([rustdoc] Replace module list items `ul`/`li` with `dl`/`dd`/`dt` elements) - rust-lang#135703 (Disallow `A { .. }` if `A` has no fields) - rust-lang#135705 (Consolidate ad-hoc MIR lints into real pass-manager-based MIR lints) - rust-lang#135708 (Some random compiler nits) Failed merges: - rust-lang#135685 (Remove unused `item-row` CSS class) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 01706e1 + c87dd96 commit 9857284

File tree

64 files changed

+394
-353
lines changed

Some content is hidden

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

64 files changed

+394
-353
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -1991,18 +1991,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19911991
adt_ty: Ty<'tcx>,
19921992
expected: Expectation<'tcx>,
19931993
expr: &hir::Expr<'_>,
1994-
span: Span,
1994+
path_span: Span,
19951995
variant: &'tcx ty::VariantDef,
19961996
hir_fields: &'tcx [hir::ExprField<'tcx>],
19971997
base_expr: &'tcx hir::StructTailExpr<'tcx>,
19981998
) {
19991999
let tcx = self.tcx;
20002000

2001-
let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
2001+
let adt_ty = self.try_structurally_resolve_type(path_span, adt_ty);
20022002
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
20032003
self.fudge_inference_if_ok(|| {
20042004
let ocx = ObligationCtxt::new(self);
2005-
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
2005+
ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;
20062006
if !ocx.select_where_possible().is_empty() {
20072007
return Err(TypeError::Mismatch);
20082008
}
@@ -2012,11 +2012,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20122012
});
20132013
if let Some(adt_ty_hint) = adt_ty_hint {
20142014
// re-link the variables that the fudging above can create.
2015-
self.demand_eqtype(span, adt_ty_hint, adt_ty);
2015+
self.demand_eqtype(path_span, adt_ty_hint, adt_ty);
20162016
}
20172017

20182018
let ty::Adt(adt, args) = adt_ty.kind() else {
2019-
span_bug!(span, "non-ADT passed to check_expr_struct_fields");
2019+
span_bug!(path_span, "non-ADT passed to check_expr_struct_fields");
20202020
};
20212021
let adt_kind = adt.adt_kind();
20222022

@@ -2107,7 +2107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21072107
if adt_kind == AdtKind::Union && hir_fields.len() != 1 {
21082108
struct_span_code_err!(
21092109
self.dcx(),
2110-
span,
2110+
path_span,
21112111
E0784,
21122112
"union expressions should have exactly one field",
21132113
)
@@ -2167,6 +2167,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21672167
});
21682168
return;
21692169
}
2170+
if variant.fields.is_empty() {
2171+
let mut err = self.dcx().struct_span_err(
2172+
span,
2173+
format!(
2174+
"`{adt_ty}` has no fields, `..` needs at least one default field in the \
2175+
struct definition",
2176+
),
2177+
);
2178+
err.span_label(path_span, "this type has no fields");
2179+
err.emit();
2180+
}
21702181
if !missing_mandatory_fields.is_empty() {
21712182
let s = pluralize!(missing_mandatory_fields.len());
21722183
let fields: Vec<_> =
@@ -2316,11 +2327,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23162327
.collect();
23172328

23182329
if !private_fields.is_empty() {
2319-
self.report_private_fields(adt_ty, span, expr.span, private_fields, hir_fields);
2330+
self.report_private_fields(
2331+
adt_ty,
2332+
path_span,
2333+
expr.span,
2334+
private_fields,
2335+
hir_fields,
2336+
);
23202337
} else {
23212338
self.report_missing_fields(
23222339
adt_ty,
2323-
span,
2340+
path_span,
23242341
remaining_fields,
23252342
variant,
23262343
hir_fields,

compiler/rustc_hir_typeck/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
8787
}
8888

8989
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
90-
typeck_with_fallback(tcx, def_id, None)
90+
typeck_with_inspect(tcx, def_id, None)
9191
}
9292

9393
/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation.
@@ -99,11 +99,11 @@ pub fn inspect_typeck<'tcx>(
9999
def_id: LocalDefId,
100100
inspect: ObligationInspector<'tcx>,
101101
) -> &'tcx ty::TypeckResults<'tcx> {
102-
typeck_with_fallback(tcx, def_id, Some(inspect))
102+
typeck_with_inspect(tcx, def_id, Some(inspect))
103103
}
104104

105105
#[instrument(level = "debug", skip(tcx, inspector), ret)]
106-
fn typeck_with_fallback<'tcx>(
106+
fn typeck_with_inspect<'tcx>(
107107
tcx: TyCtxt<'tcx>,
108108
def_id: LocalDefId,
109109
inspector: Option<ObligationInspector<'tcx>>,

compiler/rustc_interface/src/passes.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
875875
});
876876
// Freeze definitions as we don't add new ones at this point.
877877
// We need to wait until now since we synthesize a by-move body
878+
// for all coroutine-closures.
879+
//
878880
// This improves performance by allowing lock-free access to them.
879881
tcx.untracked().definitions.freeze();
880882

@@ -887,7 +889,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
887889
});
888890
});
889891
sess.time("MIR_effect_checking", || {
890-
for def_id in tcx.hir().body_owners() {
892+
tcx.hir().par_body_owners(|def_id| {
891893
tcx.ensure().has_ffi_unwind_calls(def_id);
892894

893895
// If we need to codegen, ensure that we emit all errors from
@@ -898,15 +900,17 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
898900
{
899901
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
900902
}
901-
}
903+
});
902904
});
903-
tcx.hir().par_body_owners(|def_id| {
904-
if tcx.is_coroutine(def_id.to_def_id()) {
905-
tcx.ensure().mir_coroutine_witnesses(def_id);
906-
tcx.ensure().check_coroutine_obligations(
907-
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
908-
);
909-
}
905+
sess.time("coroutine_obligations", || {
906+
tcx.hir().par_body_owners(|def_id| {
907+
if tcx.is_coroutine(def_id.to_def_id()) {
908+
tcx.ensure().mir_coroutine_witnesses(def_id);
909+
tcx.ensure().check_coroutine_obligations(
910+
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
911+
);
912+
}
913+
});
910914
});
911915

912916
sess.time("layout_testing", || layout_test::test_layout(tcx));

compiler/rustc_middle/src/query/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1164,8 +1164,7 @@ rustc_queries! {
11641164
}
11651165

11661166
/// Check whether the function has any recursion that could cause the inliner to trigger
1167-
/// a cycle. Returns the call stack causing the cycle. The call stack does not contain the
1168-
/// current function, just all intermediate functions.
1167+
/// a cycle.
11691168
query mir_callgraph_reachable(key: (ty::Instance<'tcx>, LocalDefId)) -> bool {
11701169
fatal_cycle
11711170
desc { |tcx|

compiler/rustc_mir_build/messages.ftl

-12
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
118118
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
119119
.label = use of extern static
120120
121-
mir_build_force_inline =
122-
`{$callee}` is incompatible with `#[rustc_force_inline]`
123-
.attr = annotation here
124-
.callee = `{$callee}` defined here
125-
.note = incompatible due to: {$reason}
126-
127121
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
128122
129123
mir_build_initializing_type_with_requires_unsafe =
@@ -330,12 +324,6 @@ mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/s
330324
mir_build_type_not_structural_tip =
331325
the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
332326
333-
mir_build_unconditional_recursion = function cannot return without recursing
334-
.label = cannot return without recursing
335-
.help = a `loop` may express intention better if this is on purpose
336-
337-
mir_build_unconditional_recursion_call_site_label = recursive call site
338-
339327
mir_build_union_field_requires_unsafe =
340328
access to union field is unsafe and requires unsafe block
341329
.note = the field may not be properly initialized: using uninitialized data will cause undefined behavior

compiler/rustc_mir_build/src/builder/mod.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@ use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode
2626
use rustc_middle::{bug, span_bug};
2727
use rustc_span::{Span, Symbol, sym};
2828

29-
use super::lints;
3029
use crate::builder::expr::as_place::PlaceBuilder;
3130
use crate::builder::scope::DropKind;
32-
use crate::check_inline;
3331

3432
pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
3533
tcx: TyCtxt<'tcx>,
@@ -48,7 +46,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
4846
}
4947

5048
/// Construct the MIR for a given `DefId`.
51-
pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
49+
pub(crate) fn build_mir<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
5250
let tcx = tcx.tcx;
5351
tcx.ensure_with_value().thir_abstract_const(def);
5452
if let Err(e) = tcx.check_match(def) {
@@ -80,9 +78,6 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx
8078
}
8179
};
8280

83-
lints::check(tcx, &body);
84-
check_inline::check_force_inline(tcx, &body);
85-
8681
// The borrow checker will replace all the regions here with its own
8782
// inference variables. There's no point having non-erased regions here.
8883
// The exception is `body.user_type_annotations`, which is used unmodified

compiler/rustc_mir_build/src/errors.rs

-22
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,6 @@ use rustc_span::{Span, Symbol};
1111

1212
use crate::fluent_generated as fluent;
1313

14-
#[derive(LintDiagnostic)]
15-
#[diag(mir_build_unconditional_recursion)]
16-
#[help]
17-
pub(crate) struct UnconditionalRecursion {
18-
#[label]
19-
pub(crate) span: Span,
20-
#[label(mir_build_unconditional_recursion_call_site_label)]
21-
pub(crate) call_sites: Vec<Span>,
22-
}
23-
2414
#[derive(LintDiagnostic)]
2515
#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)]
2616
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
@@ -1107,15 +1097,3 @@ impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> {
11071097
);
11081098
}
11091099
}
1110-
1111-
#[derive(Diagnostic)]
1112-
#[diag(mir_build_force_inline)]
1113-
#[note]
1114-
pub(crate) struct InvalidForceInline {
1115-
#[primary_span]
1116-
pub attr_span: Span,
1117-
#[label(mir_build_callee)]
1118-
pub callee_span: Span,
1119-
pub callee: String,
1120-
pub reason: &'static str,
1121-
}

compiler/rustc_mir_build/src/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515
// "Go to file" feature to silently ignore all files in the module, probably
1616
// because it assumes that "build" is a build-output directory. See #134365.
1717
mod builder;
18-
pub mod check_inline;
1918
mod check_tail_calls;
2019
mod check_unsafety;
2120
mod errors;
22-
pub mod lints;
2321
mod thir;
2422

2523
use rustc_middle::util::Providers;
@@ -29,7 +27,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
2927
pub fn provide(providers: &mut Providers) {
3028
providers.check_match = thir::pattern::check_match;
3129
providers.lit_to_const = thir::constant::lit_to_const;
32-
providers.hooks.build_mir = builder::mir_build;
30+
providers.hooks.build_mir = builder::build_mir;
3331
providers.closure_saved_names_of_captured_variables =
3432
builder::closure_saved_names_of_captured_variables;
3533
providers.check_unsafety = check_unsafety::check_unsafety;

compiler/rustc_mir_transform/messages.ftl

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ mir_transform_force_inline =
2727
.callee = `{$callee}` defined here
2828
.note = could not be inlined due to: {$reason}
2929
30+
mir_transform_force_inline_attr =
31+
`{$callee}` is incompatible with `#[rustc_force_inline]`
32+
.attr = annotation here
33+
.callee = `{$callee}` defined here
34+
.note = incompatible due to: {$reason}
35+
3036
mir_transform_force_inline_justification =
3137
`{$callee}` is required to be inlined to: {$sym}
3238
@@ -66,6 +72,12 @@ mir_transform_unaligned_packed_ref = reference to packed field is unaligned
6672
.note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
6773
.help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
6874
75+
mir_transform_unconditional_recursion = function cannot return without recursing
76+
.label = cannot return without recursing
77+
.help = a `loop` may express intention better if this is on purpose
78+
79+
mir_transform_unconditional_recursion_call_site_label = recursive call site
80+
6981
mir_transform_undefined_transmute = pointers cannot be transmuted to integers during const eval
7082
.note = at compile-time, pointers do not have an integer value
7183
.note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior

compiler/rustc_mir_build/src/lints.rs compiler/rustc_mir_transform/src/check_call_recursion.rs

+43-38
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,54 @@ use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
1010
use rustc_span::Span;
1111

1212
use crate::errors::UnconditionalRecursion;
13+
use crate::pass_manager::MirLint;
1314

14-
pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
15-
check_call_recursion(tcx, body);
15+
pub(super) struct CheckCallRecursion;
16+
17+
impl<'tcx> MirLint<'tcx> for CheckCallRecursion {
18+
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
19+
let def_id = body.source.def_id().expect_local();
20+
21+
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
22+
// If this is trait/impl method, extract the trait's args.
23+
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
24+
Some(trait_def_id) => {
25+
let trait_args_count = tcx.generics_of(trait_def_id).count();
26+
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
27+
}
28+
_ => &[],
29+
};
30+
31+
check_recursion(tcx, body, CallRecursion { trait_args })
32+
}
33+
}
1634
}
1735

18-
fn check_call_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
19-
let def_id = body.source.def_id().expect_local();
36+
/// Requires drop elaboration to have been performed.
37+
pub(super) struct CheckDropRecursion;
2038

21-
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
22-
// If this is trait/impl method, extract the trait's args.
23-
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
24-
Some(trait_def_id) => {
25-
let trait_args_count = tcx.generics_of(trait_def_id).count();
26-
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
27-
}
28-
_ => &[],
29-
};
39+
impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
40+
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
41+
let def_id = body.source.def_id().expect_local();
3042

31-
check_recursion(tcx, body, CallRecursion { trait_args })
43+
// First check if `body` is an `fn drop()` of `Drop`
44+
if let DefKind::AssocFn = tcx.def_kind(def_id)
45+
&& let Some(trait_ref) =
46+
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
47+
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
48+
&& drop_trait == trait_ref.instantiate_identity().def_id
49+
// avoid erroneous `Drop` impls from causing ICEs below
50+
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
51+
&& sig.inputs().skip_binder().len() == 1
52+
{
53+
// It was. Now figure out for what type `Drop` is implemented and then
54+
// check for recursion.
55+
if let ty::Ref(_, dropped_ty, _) =
56+
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
57+
{
58+
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
59+
}
60+
}
3261
}
3362
}
3463

@@ -61,30 +90,6 @@ fn check_recursion<'tcx>(
6190
}
6291
}
6392

64-
/// Requires drop elaboration to have been performed first.
65-
pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
66-
let def_id = body.source.def_id().expect_local();
67-
68-
// First check if `body` is an `fn drop()` of `Drop`
69-
if let DefKind::AssocFn = tcx.def_kind(def_id)
70-
&& let Some(trait_ref) =
71-
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
72-
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
73-
&& drop_trait == trait_ref.instantiate_identity().def_id
74-
// avoid erroneous `Drop` impls from causing ICEs below
75-
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
76-
&& sig.inputs().skip_binder().len() == 1
77-
{
78-
// It was. Now figure out for what type `Drop` is implemented and then
79-
// check for recursion.
80-
if let ty::Ref(_, dropped_ty, _) =
81-
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
82-
{
83-
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
84-
}
85-
}
86-
}
87-
8893
trait TerminatorClassifier<'tcx> {
8994
fn is_recursive_terminator(
9095
&self,

0 commit comments

Comments
 (0)