Skip to content

Commit

Permalink
Auto merge of rust-lang#135715 - matthiaskrgr:rollup-9a18sxj, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

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
  • Loading branch information
bors committed Jan 19, 2025
2 parents 01706e1 + c87dd96 commit 9857284
Show file tree
Hide file tree
Showing 64 changed files with 394 additions and 353 deletions.
33 changes: 25 additions & 8 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1991,18 +1991,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
adt_ty: Ty<'tcx>,
expected: Expectation<'tcx>,
expr: &hir::Expr<'_>,
span: Span,
path_span: Span,
variant: &'tcx ty::VariantDef,
hir_fields: &'tcx [hir::ExprField<'tcx>],
base_expr: &'tcx hir::StructTailExpr<'tcx>,
) {
let tcx = self.tcx;

let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
let adt_ty = self.try_structurally_resolve_type(path_span, adt_ty);
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
self.fudge_inference_if_ok(|| {
let ocx = ObligationCtxt::new(self);
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;
if !ocx.select_where_possible().is_empty() {
return Err(TypeError::Mismatch);
}
Expand All @@ -2012,11 +2012,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
if let Some(adt_ty_hint) = adt_ty_hint {
// re-link the variables that the fudging above can create.
self.demand_eqtype(span, adt_ty_hint, adt_ty);
self.demand_eqtype(path_span, adt_ty_hint, adt_ty);
}

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

Expand Down Expand Up @@ -2107,7 +2107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if adt_kind == AdtKind::Union && hir_fields.len() != 1 {
struct_span_code_err!(
self.dcx(),
span,
path_span,
E0784,
"union expressions should have exactly one field",
)
Expand Down Expand Up @@ -2167,6 +2167,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
return;
}
if variant.fields.is_empty() {
let mut err = self.dcx().struct_span_err(
span,
format!(
"`{adt_ty}` has no fields, `..` needs at least one default field in the \
struct definition",
),
);
err.span_label(path_span, "this type has no fields");
err.emit();
}
if !missing_mandatory_fields.is_empty() {
let s = pluralize!(missing_mandatory_fields.len());
let fields: Vec<_> =
Expand Down Expand Up @@ -2316,11 +2327,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect();

if !private_fields.is_empty() {
self.report_private_fields(adt_ty, span, expr.span, private_fields, hir_fields);
self.report_private_fields(
adt_ty,
path_span,
expr.span,
private_fields,
hir_fields,
);
} else {
self.report_missing_fields(
adt_ty,
span,
path_span,
remaining_fields,
variant,
hir_fields,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
}

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

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

#[instrument(level = "debug", skip(tcx, inspector), ret)]
fn typeck_with_fallback<'tcx>(
fn typeck_with_inspect<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
inspector: Option<ObligationInspector<'tcx>>,
Expand Down
22 changes: 13 additions & 9 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
});
// Freeze definitions as we don't add new ones at this point.
// We need to wait until now since we synthesize a by-move body
// for all coroutine-closures.
//
// This improves performance by allowing lock-free access to them.
tcx.untracked().definitions.freeze();

Expand All @@ -887,7 +889,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
});
});
sess.time("MIR_effect_checking", || {
for def_id in tcx.hir().body_owners() {
tcx.hir().par_body_owners(|def_id| {
tcx.ensure().has_ffi_unwind_calls(def_id);

// If we need to codegen, ensure that we emit all errors from
Expand All @@ -898,15 +900,17 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
{
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
}
}
});
});
tcx.hir().par_body_owners(|def_id| {
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure().mir_coroutine_witnesses(def_id);
tcx.ensure().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
);
}
sess.time("coroutine_obligations", || {
tcx.hir().par_body_owners(|def_id| {
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure().mir_coroutine_witnesses(def_id);
tcx.ensure().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
);
}
});
});

sess.time("layout_testing", || layout_test::test_layout(tcx));
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,7 @@ rustc_queries! {
}

/// Check whether the function has any recursion that could cause the inliner to trigger
/// a cycle. Returns the call stack causing the cycle. The call stack does not contain the
/// current function, just all intermediate functions.
/// a cycle.
query mir_callgraph_reachable(key: (ty::Instance<'tcx>, LocalDefId)) -> bool {
fatal_cycle
desc { |tcx|
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
.label = use of extern static
mir_build_force_inline =
`{$callee}` is incompatible with `#[rustc_force_inline]`
.attr = annotation here
.callee = `{$callee}` defined here
.note = incompatible due to: {$reason}
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
mir_build_initializing_type_with_requires_unsafe =
Expand Down Expand Up @@ -330,12 +324,6 @@ mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/s
mir_build_type_not_structural_tip =
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
mir_build_unconditional_recursion = function cannot return without recursing
.label = cannot return without recursing
.help = a `loop` may express intention better if this is on purpose
mir_build_unconditional_recursion_call_site_label = recursive call site
mir_build_union_field_requires_unsafe =
access to union field is unsafe and requires unsafe block
.note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_mir_build/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, Symbol, sym};

use super::lints;
use crate::builder::expr::as_place::PlaceBuilder;
use crate::builder::scope::DropKind;
use crate::check_inline;

pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
tcx: TyCtxt<'tcx>,
Expand All @@ -48,7 +46,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
}

/// Construct the MIR for a given `DefId`.
pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
pub(crate) fn build_mir<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
let tcx = tcx.tcx;
tcx.ensure_with_value().thir_abstract_const(def);
if let Err(e) = tcx.check_match(def) {
Expand Down Expand Up @@ -80,9 +78,6 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx
}
};

lints::check(tcx, &body);
check_inline::check_force_inline(tcx, &body);

// The borrow checker will replace all the regions here with its own
// inference variables. There's no point having non-erased regions here.
// The exception is `body.user_type_annotations`, which is used unmodified
Expand Down
22 changes: 0 additions & 22 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ use rustc_span::{Span, Symbol};

use crate::fluent_generated as fluent;

#[derive(LintDiagnostic)]
#[diag(mir_build_unconditional_recursion)]
#[help]
pub(crate) struct UnconditionalRecursion {
#[label]
pub(crate) span: Span,
#[label(mir_build_unconditional_recursion_call_site_label)]
pub(crate) call_sites: Vec<Span>,
}

#[derive(LintDiagnostic)]
#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)]
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
Expand Down Expand Up @@ -1107,15 +1097,3 @@ impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> {
);
}
}

#[derive(Diagnostic)]
#[diag(mir_build_force_inline)]
#[note]
pub(crate) struct InvalidForceInline {
#[primary_span]
pub attr_span: Span,
#[label(mir_build_callee)]
pub callee_span: Span,
pub callee: String,
pub reason: &'static str,
}
4 changes: 1 addition & 3 deletions compiler/rustc_mir_build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
// "Go to file" feature to silently ignore all files in the module, probably
// because it assumes that "build" is a build-output directory. See #134365.
mod builder;
pub mod check_inline;
mod check_tail_calls;
mod check_unsafety;
mod errors;
pub mod lints;
mod thir;

use rustc_middle::util::Providers;
Expand All @@ -29,7 +27,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
pub fn provide(providers: &mut Providers) {
providers.check_match = thir::pattern::check_match;
providers.lit_to_const = thir::constant::lit_to_const;
providers.hooks.build_mir = builder::mir_build;
providers.hooks.build_mir = builder::build_mir;
providers.closure_saved_names_of_captured_variables =
builder::closure_saved_names_of_captured_variables;
providers.check_unsafety = check_unsafety::check_unsafety;
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_mir_transform/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ mir_transform_force_inline =
.callee = `{$callee}` defined here
.note = could not be inlined due to: {$reason}
mir_transform_force_inline_attr =
`{$callee}` is incompatible with `#[rustc_force_inline]`
.attr = annotation here
.callee = `{$callee}` defined here
.note = incompatible due to: {$reason}
mir_transform_force_inline_justification =
`{$callee}` is required to be inlined to: {$sym}
Expand Down Expand Up @@ -66,6 +72,12 @@ mir_transform_unaligned_packed_ref = reference to packed field is unaligned
.note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
.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)
mir_transform_unconditional_recursion = function cannot return without recursing
.label = cannot return without recursing
.help = a `loop` may express intention better if this is on purpose
mir_transform_unconditional_recursion_call_site_label = recursive call site
mir_transform_undefined_transmute = pointers cannot be transmuted to integers during const eval
.note = at compile-time, pointers do not have an integer value
.note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,54 @@ use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
use rustc_span::Span;

use crate::errors::UnconditionalRecursion;
use crate::pass_manager::MirLint;

pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
check_call_recursion(tcx, body);
pub(super) struct CheckCallRecursion;

impl<'tcx> MirLint<'tcx> for CheckCallRecursion {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id().expect_local();

if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
// If this is trait/impl method, extract the trait's args.
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
Some(trait_def_id) => {
let trait_args_count = tcx.generics_of(trait_def_id).count();
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
}
_ => &[],
};

check_recursion(tcx, body, CallRecursion { trait_args })
}
}
}

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

if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
// If this is trait/impl method, extract the trait's args.
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
Some(trait_def_id) => {
let trait_args_count = tcx.generics_of(trait_def_id).count();
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
}
_ => &[],
};
impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id().expect_local();

check_recursion(tcx, body, CallRecursion { trait_args })
// First check if `body` is an `fn drop()` of `Drop`
if let DefKind::AssocFn = tcx.def_kind(def_id)
&& let Some(trait_ref) =
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
&& drop_trait == trait_ref.instantiate_identity().def_id
// avoid erroneous `Drop` impls from causing ICEs below
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
&& sig.inputs().skip_binder().len() == 1
{
// It was. Now figure out for what type `Drop` is implemented and then
// check for recursion.
if let ty::Ref(_, dropped_ty, _) =
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
{
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
}
}
}
}

Expand Down Expand Up @@ -61,30 +90,6 @@ fn check_recursion<'tcx>(
}
}

/// Requires drop elaboration to have been performed first.
pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id().expect_local();

// First check if `body` is an `fn drop()` of `Drop`
if let DefKind::AssocFn = tcx.def_kind(def_id)
&& let Some(trait_ref) =
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
&& drop_trait == trait_ref.instantiate_identity().def_id
// avoid erroneous `Drop` impls from causing ICEs below
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
&& sig.inputs().skip_binder().len() == 1
{
// It was. Now figure out for what type `Drop` is implemented and then
// check for recursion.
if let ty::Ref(_, dropped_ty, _) =
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
{
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
}
}
}

trait TerminatorClassifier<'tcx> {
fn is_recursive_terminator(
&self,
Expand Down
Loading

0 comments on commit 9857284

Please sign in to comment.