Skip to content

Commit

Permalink
Auto merge of #123725 - GuillaumeGomez:rollup-gk2bbrg, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #118391 (Add `REDUNDANT_LIFETIMES` lint to detect lifetimes which are semantically redundant)
 - #123534 (Windows: set main thread name without re-encoding)
 - #123659 (Add support to intrinsics fallback body)
 - #123689 (Add const generics support for pattern types)
 - #123701 (Only assert for child/parent projection compatibility AFTER checking that theyre coming from the same place)
 - #123702 (Further cleanup cfgs in the UI test suite)
 - #123706 (rustdoc: reduce per-page HTML overhead)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 10, 2024
2 parents e908cfd + 96628f4 commit 5974fe8
Show file tree
Hide file tree
Showing 50 changed files with 749 additions and 236 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
}
}

#[macro_export]
macro_rules! into_diag_arg_using_display {
($( $ty:ty ),+ $(,)?) => {
$(
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pa
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
.label = not allowed in type signatures
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
hir_analysis_return_type_notation_equality_bound =
Expand Down
135 changes: 135 additions & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_macros::LintDiagnostic;
use rustc_middle::query::Providers;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
Expand Down Expand Up @@ -136,6 +138,8 @@ where
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);

lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);

let errors = infcx.resolve_regions(&outlives_env);
if errors.is_empty() {
return Ok(());
Expand Down Expand Up @@ -2010,6 +2014,137 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
res
}

fn lint_redundant_lifetimes<'tcx>(
tcx: TyCtxt<'tcx>,
owner_id: LocalDefId,
outlives_env: &OutlivesEnvironment<'tcx>,
) {
let def_kind = tcx.def_kind(owner_id);
match def_kind {
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::Fn
| DefKind::Const
| DefKind::Impl { of_trait: _ } => {
// Proceed
}
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
let parent_def_id = tcx.local_parent(owner_id);
if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) {
// Don't check for redundant lifetimes for associated items of trait
// implementations, since the signature is required to be compatible
// with the trait, even if the implementation implies some lifetimes
// are redundant.
return;
}
}
DefKind::Mod
| DefKind::Variant
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TyParam
| DefKind::ConstParam
| DefKind::Static { .. }
| DefKind::Ctor(_, _)
| DefKind::Macro(_)
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Closure => return,
}

// The ordering of this lifetime map is a bit subtle.
//
// Specifically, we want to find a "candidate" lifetime that precedes a "victim" lifetime,
// where we can prove that `'candidate = 'victim`.
//
// `'static` must come first in this list because we can never replace `'static` with
// something else, but if we find some lifetime `'a` where `'a = 'static`, we want to
// suggest replacing `'a` with `'static`.
let mut lifetimes = vec![tcx.lifetimes.re_static];
lifetimes.extend(
ty::GenericArgs::identity_for_item(tcx, owner_id).iter().filter_map(|arg| arg.as_region()),
);
// If we are in a function, add its late-bound lifetimes too.
if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
for var in tcx.fn_sig(owner_id).instantiate_identity().bound_vars() {
let ty::BoundVariableKind::Region(kind) = var else { continue };
lifetimes.push(ty::Region::new_late_param(tcx, owner_id.to_def_id(), kind));
}
}
lifetimes.retain(|candidate| candidate.has_name());

// Keep track of lifetimes which have already been replaced with other lifetimes.
// This makes sure that if `'a = 'b = 'c`, we don't say `'c` should be replaced by
// both `'a` and `'b`.
let mut shadowed = FxHashSet::default();

for (idx, &candidate) in lifetimes.iter().enumerate() {
// Don't suggest removing a lifetime twice. We only need to check this
// here and not up in the `victim` loop because equality is transitive,
// so if A = C and B = C, then A must = B, so it'll be shadowed too in
// A's victim loop.
if shadowed.contains(&candidate) {
continue;
}

for &victim in &lifetimes[(idx + 1)..] {
// We should only have late-bound lifetimes of the `BrNamed` variety,
// since we get these signatures straight from `hir_lowering`. And any
// other regions (ReError/ReStatic/etc.) shouldn't matter, since we
// can't really suggest to remove them.
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
| ty::ReLateParam(ty::LateParamRegion {
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
..
})) = victim.kind()
else {
continue;
};

// Do not rename lifetimes not local to this item since they'll overlap
// with the lint running on the parent. We still want to consider parent
// lifetimes which make child lifetimes redundant, otherwise we would
// have truncated the `identity_for_item` args above.
if tcx.parent(def_id) != owner_id.to_def_id() {
continue;
}

// If `candidate <: victim` and `victim <: candidate`, then they're equal.
if outlives_env.free_region_map().sub_free_regions(tcx, candidate, victim)
&& outlives_env.free_region_map().sub_free_regions(tcx, victim, candidate)
{
shadowed.insert(victim);
tcx.emit_node_span_lint(
rustc_lint_defs::builtin::REDUNDANT_LIFETIMES,
tcx.local_def_id_to_hir_id(def_id.expect_local()),
tcx.def_span(def_id),
RedundantLifetimeArgsLint { candidate, victim },
);
}
}
}
}

#[derive(LintDiagnostic)]
#[diag(hir_analysis_redundant_lifetime_args)]
#[note]
struct RedundantLifetimeArgsLint<'tcx> {
/// The lifetime we have found to be redundant.
victim: ty::Region<'tcx>,
// The lifetime we can replace the victim with.
candidate: ty::Region<'tcx>,
}

pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
}
26 changes: 0 additions & 26 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
Expand Down Expand Up @@ -867,31 +866,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}) => {
self.visit_lifetime(lifetime);
walk_list!(self, visit_param_bound, bounds);

if lifetime.res != hir::LifetimeName::Static {
for bound in bounds {
let hir::GenericBound::Outlives(lt) = bound else {
continue;
};
if lt.res != hir::LifetimeName::Static {
continue;
}
self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
self.tcx.node_span_lint(
lint::builtin::UNUSED_LIFETIMES,
lifetime.hir_id,
lifetime.ident.span,
format!("unnecessary lifetime parameter `{}`", lifetime.ident),
|lint| {
let help = format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.ident,
);
lint.help(help);
},
);
}
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
self.visit_ty(lhs_ty);
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Err(LitToConstError::TypeError) => todo!(),
}
}

hir::ExprKind::Path(hir::QPath::Resolved(
_,
&hir::Path {
res: Res::Def(DefKind::ConstParam, def_id), ..
},
)) => {
let ty = tcx
.type_of(def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
let item_def_id = tcx.parent(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty)
}

_ => {
let err = tcx
.dcx()
Expand Down
28 changes: 28 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ declare_lint_pass! {
PROC_MACRO_BACK_COMPAT,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
REDUNDANT_LIFETIMES,
REFINING_IMPL_TRAIT_INTERNAL,
REFINING_IMPL_TRAIT_REACHABLE,
RENAMED_AND_REMOVED_LINTS,
Expand Down Expand Up @@ -1707,6 +1708,33 @@ declare_lint! {
"detects lifetime parameters that are never used"
}

declare_lint! {
/// The `redundant_lifetimes` lint detects lifetime parameters that are
/// redundant because they are equal to another named lifetime.
///
/// ### Example
///
/// ```rust,compile_fail
/// #[deny(redundant_lifetimes)]
///
/// // `'a = 'static`, so all usages of `'a` can be replaced with `'static`
/// pub fn bar<'a: 'static>() {}
///
/// // `'a = 'b`, so all usages of `'b` can be replaced with `'a`
/// pub fn bar<'a: 'b, 'b: 'a>() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Unused lifetime parameters may signal a mistake or unfinished code.
/// Consider removing the parameter.
pub REDUNDANT_LIFETIMES,
Allow,
"detects lifetime parameters that are redundant because they are equal to some other named lifetime"
}

declare_lint! {
/// The `tyvar_behind_raw_pointer` lint detects raw pointer to an
/// inference variable.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ pub struct GlobalCtxt<'tcx> {
impl<'tcx> GlobalCtxt<'tcx> {
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
/// `f`.
pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
pub fn enter<F, R>(&'tcx self, f: F) -> R
where
F: FnOnce(TyCtxt<'tcx>) -> R,
{
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@ use std::fmt::Write;
use std::ops::ControlFlow;

use crate::ty::{
AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque, PolyTraitPredicate,
Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitor,
self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque,
PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
};

use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg};
use rustc_errors::{into_diag_arg_using_display, Applicability, Diag, DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{PredicateOrigin, WherePredicate};
use rustc_span::{BytePos, Span};
use rustc_type_ir::TyKind::*;

impl<'tcx> IntoDiagArg for Ty<'tcx> {
fn into_diag_arg(self) -> DiagArgValue {
self.to_string().into_diag_arg()
}
into_diag_arg_using_display! {
Ty<'_>,
ty::Region<'_>,
}

impl<'tcx> Ty<'tcx> {
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
}) {
let (child_field_idx, child_capture) = child_captures.next().unwrap();

// This analysis only makes sense if the parent capture is a
// prefix of the child capture.
assert!(
child_capture.place.projections.len() >= parent_capture.place.projections.len(),
"parent capture ({parent_capture:#?}) expected to be prefix of \
child capture ({child_capture:#?})"
);

// Store this set of additional projections (fields and derefs).
// We need to re-apply them later.
let child_precise_captures =
Expand Down Expand Up @@ -244,7 +252,6 @@ fn child_prefix_matches_parent_projections(
bug!("expected capture to be an upvar");
};

assert!(child_capture.place.projections.len() >= parent_capture.place.projections.len());
parent_base.var_path.hir_id == child_base.var_path.hir_id
&& std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
.all(|(child, parent)| child.kind == parent.kind)
Expand Down
Loading

0 comments on commit 5974fe8

Please sign in to comment.