Skip to content

Commit

Permalink
Only use implied bounds hack if bevy, and use deeply normalize in imp…
Browse files Browse the repository at this point in the history
…lied bounds hack
  • Loading branch information
compiler-errors committed Mar 4, 2025
1 parent fd17dea commit d759958
Show file tree
Hide file tree
Showing 19 changed files with 264 additions and 269 deletions.
66 changes: 18 additions & 48 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,14 @@ where

let infcx_compat = infcx.fork();

// We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always.
// We specifically want to *disable* the implied bounds hack, first,
// so we can detect when failures are due to bevy's implied bounds.
let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
&infcx,
body_def_id,
param_env,
assumed_wf_types.iter().copied(),
false,
true,
);

lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);
Expand All @@ -142,53 +143,22 @@ where
return Ok(());
}

let is_bevy = assumed_wf_types.visit_with(&mut ContainsBevyParamSet { tcx }).is_break();

// If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
// We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
// but that does result in slightly more work when this option is set and
// just obscures what we mean here anyways. Let's just be explicit.
if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
&infcx,
body_def_id,
param_env,
assumed_wf_types,
true,
);
let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
if errors_compat.is_empty() {
Ok(())
} else {
Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
}
let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(
&infcx_compat,
body_def_id,
param_env,
assumed_wf_types,
// Don't *disable* the implied bounds hack; though this will only apply
// the implied bounds hack if this contains `bevy_ecs`'s `ParamSet` type.
false,
);
let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);
if errors_compat.is_empty() {
// FIXME: Once we fix bevy, this would be the place to insert a warning
// to upgrade bevy.
Ok(())
} else {
Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors))
}
}

struct ContainsBevyParamSet<'tcx> {
tcx: TyCtxt<'tcx>,
}

impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> {
type Result = ControlFlow<()>;

fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
// We only care to match `ParamSet<T>` or `&ParamSet<T>`.
match t.kind() {
ty::Adt(def, _) => {
if self.tcx.item_name(def.did()) == sym::ParamSet
&& self.tcx.crate_name(def.did().krate) == sym::bevy_ecs
{
return ControlFlow::Break(());
}
}
ty::Ref(_, ty, _) => ty.visit_with(self)?,
_ => {}
}

ControlFlow::Continue(())
Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/query/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,14 @@ impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
}
}

impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) {
type Cache<V> = DefaultCache<Self, V>;

fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}

impl Key for (Symbol, u32, u32) {
type Cache<V> = DefaultCache<Self, V>;

Expand Down
13 changes: 2 additions & 11 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2262,22 +2262,13 @@ rustc_queries! {
desc { "normalizing `{}`", goal.value }
}

query implied_outlives_bounds_compat(
goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
) -> Result<
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
NoSolution,
> {
desc { "computing implied outlives bounds for `{}`", goal.canonical.value.value.ty }
}

query implied_outlives_bounds(
goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool)
) -> Result<
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
NoSolution,
> {
desc { "computing implied outlives bounds v2 for `{}`", goal.canonical.value.value.ty }
desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 }
}

/// Do not call this query directly:
Expand Down
14 changes: 4 additions & 10 deletions compiler/rustc_trait_selection/src/regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,15 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
) -> Self {
Self::new_with_implied_bounds_compat(
infcx,
body_id,
param_env,
assumed_wf_tys,
!infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat,
)
Self::new_with_implied_bounds_compat(infcx, body_id, param_env, assumed_wf_tys, false)
}

fn new_with_implied_bounds_compat(
infcx: &InferCtxt<'tcx>,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
implied_bounds_compat: bool,
disable_implied_bounds_hack: bool,
) -> Self {
let mut bounds = vec![];

Expand Down Expand Up @@ -59,11 +53,11 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
OutlivesEnvironment::from_normalized_bounds(
param_env,
bounds,
infcx.implied_bounds_tys_with_compat(
infcx.implied_bounds_tys(
body_id,
param_env,
assumed_wf_tys,
implied_bounds_compat,
disable_implied_bounds_hack,
),
)
}
Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn implied_outlives_bounds<'a, 'tcx>(
param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId,
ty: Ty<'tcx>,
compat: bool,
disable_implied_bounds_hack: bool,
) -> Vec<OutlivesBound<'tcx>> {
let ty = infcx.resolve_vars_if_possible(ty);
let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty);
Expand All @@ -52,11 +52,8 @@ fn implied_outlives_bounds<'a, 'tcx>(
let mut canonical_var_values = OriginalQueryValues::default();
let input = ImpliedOutlivesBounds { ty };
let canonical = infcx.canonicalize_query(param_env.and(input), &mut canonical_var_values);
let implied_bounds_result = if compat {
infcx.tcx.implied_outlives_bounds_compat(canonical)
} else {
infcx.tcx.implied_outlives_bounds(canonical)
};
let implied_bounds_result =
infcx.tcx.implied_outlives_bounds((canonical, disable_implied_bounds_hack));
let Ok(canonical_result) = implied_bounds_result else {
return vec![];
};
Expand Down Expand Up @@ -110,14 +107,15 @@ fn implied_outlives_bounds<'a, 'tcx>(
impl<'tcx> InferCtxt<'tcx> {
/// Do *NOT* call this directly. You probably want to construct a `OutlivesEnvironment`
/// instead if you're interested in the implied bounds for a given signature.
fn implied_bounds_tys_with_compat<Tys: IntoIterator<Item = Ty<'tcx>>>(
fn implied_bounds_tys<Tys: IntoIterator<Item = Ty<'tcx>>>(
&self,
body_id: LocalDefId,
param_env: ParamEnv<'tcx>,
tys: Tys,
compat: bool,
disable_implied_bounds_hack: bool,
) -> impl Iterator<Item = OutlivesBound<'tcx>> {
tys.into_iter()
.flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, ty, compat))
tys.into_iter().flat_map(move |ty| {
implied_outlives_bounds(self, param_env, body_id, ty, disable_implied_bounds_hack)
})
}
}
Loading

0 comments on commit d759958

Please sign in to comment.