Skip to content

Commit

Permalink
Simplify implementation for perf
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Nov 28, 2023
1 parent 6179ddc commit b09e25e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
45 changes: 25 additions & 20 deletions compiler/rustc_lint/src/redundant_lifetime_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{SubregionOrigin, TyCtxtInferExt};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::LintDiagnostic;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::UNUSED_LIFETIMES;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::{outlives_bounds::InferCtxtExt, ObligationCtxt};

use crate::{LateContext, LateLintPass};
Expand Down Expand Up @@ -80,17 +79,6 @@ fn check<'tcx>(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, owner_id: hir::
| DefKind::Closure => return,
}

let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);

// Compute the implied outlives bounds for the item. This ensures that we treat
// a signature with an argument like `&'a &'b ()` as implicitly having `'b: 'a`.
let Ok(assumed_wf_types) = ocx.assumed_wf_types(param_env, owner_id.def_id) else {
return;
};
let implied_bounds = infcx.implied_bounds_tys(param_env, owner_id.def_id, assumed_wf_types);
let outlives_env = &OutlivesEnvironment::with_bounds(param_env, implied_bounds);

// The ordering of this lifetime map is a bit subtle.
//
// Specifically, we want to find a "candidate" lifetime that precedes a "victim" lifetime,
Expand All @@ -111,6 +99,22 @@ fn check<'tcx>(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, owner_id: hir::
}
}

// No lifetimes except for `'static` to check.
if lifetimes.len() == 1 {
return;
}

let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);

// Compute the implied outlives bounds for the item. This ensures that we treat
// a signature with an argument like `&'a &'b ()` as implicitly having `'b: 'a`.
let Ok(assumed_wf_types) = ocx.assumed_wf_types(param_env, owner_id.def_id) else {
return;
};
let implied_bounds = infcx.implied_bounds_tys(param_env, owner_id.def_id, assumed_wf_types);
let outlives_env = &OutlivesEnvironment::with_bounds(param_env, implied_bounds);

// 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`.
Expand All @@ -128,6 +132,11 @@ fn check<'tcx>(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, owner_id: hir::
}

for &victim in &lifetimes[(idx + 1)..] {
// We should not suggest renaming `'_` in `&'static &'_ str`.
if !victim.has_name() {
continue;
}

// We only care about lifetimes that are "real", i.e. that have a def-id.
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
| ty::ReLateParam(ty::LateParamRegion {
Expand All @@ -146,14 +155,10 @@ fn check<'tcx>(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, owner_id: hir::
continue;
}

let infcx = infcx.fork();

// Require that `'candidate = 'victim`
infcx.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), candidate, victim);
infcx.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), victim, candidate);

// If there are no lifetime errors, then we have proven that `'candidate = 'victim`!
if infcx.resolve_regions(outlives_env).is_empty() {
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_spanned_lint(
UNUSED_LIFETIMES,
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/regions/transitively-redundant-lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ impl<'a> Bar<'a> {
fn d<'b: 'a>(&'b self) {} //~ ERROR unnecessary lifetime parameter `'b`
}

fn ok(x: &'static &()) {}

fn main() {}

0 comments on commit b09e25e

Please sign in to comment.