Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ pub(crate) fn type_check<'tcx>(

let polonius_context = typeck.polonius_context;

if infcx.tcx.assumptions_on_binders() {
if infcx.tcx.assumptions_on_binders_any() {
let mut converter = constraint_conversion::ConstraintConversion::new(
typeck.infcx,
typeck.universal_regions,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2369,6 +2369,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
match c {
LeafRegionConstraint::Ambiguity(_)
| LeafRegionConstraint::RegionOutlives(..)
| LeafRegionConstraint::TypeOutlives(..)
| LeafRegionConstraint::AliasTyOutlivesViaEnv(..) => (), // OK
LeafRegionConstraint::PlaceholderTyOutlives(ty, _, span) => {
// we can't check this during lowering, because the ty is a ty::Bound that gets
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
) -> U {
self.enter_forall(value, |value| {
let u = self.universe();
self.placeholder_assumptions_for_next_solver
.borrow_mut()
.insert(u, Some(rustc_type_ir::region_constraint::Assumptions::empty()));
let assumptions = self
.tcx
.assumptions_on_binders_full()
.then(rustc_type_ir::region_constraint::Assumptions::empty);
self.placeholder_assumptions_for_next_solver.borrow_mut().insert(u, assumptions);
f(value)
})
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl<'tcx> InferCtxt<'tcx> {
sub_region: Region<'tcx>,
cause: &ObligationCause<'tcx>,
) {
assert!(!self.tcx.assumptions_on_binders());
assert!(!self.tcx.assumptions_on_binders_any());

// `is_global` means the type has no params, infer, placeholder, or non-`'static`
// free regions. If the type has none of these things, then we can skip registering
Expand Down Expand Up @@ -261,7 +261,7 @@ impl<'tcx> InferCtxt<'tcx> {
assumptions: rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>,
mut conversion: impl TypeOutlivesDelegate<'tcx>,
) {
assert!(self.tcx.assumptions_on_binders());
assert!(self.tcx.assumptions_on_binders_any());
assert!(self.next_trait_solver());

let constraint = self.inner.borrow().solver_region_constraint_storage.get_constraint();
Expand Down Expand Up @@ -302,7 +302,7 @@ impl<'tcx> InferCtxt<'tcx> {
b, a, category,
);
}
AliasTyOutlivesViaEnv(..) | PlaceholderTyOutlives(..) => {
TypeOutlives(..) | AliasTyOutlivesViaEnv(..) | PlaceholderTyOutlives(..) => {
unreachable!()
}
}
Expand All @@ -326,7 +326,7 @@ impl<'tcx> InferCtxt<'tcx> {
) {
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");

if self.tcx.assumptions_on_binders() {
if self.tcx.assumptions_on_binders_any() {
self.destructure_solver_region_constraints_for_regionck(outlives_env);
}

Expand Down
30 changes: 19 additions & 11 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ use rustc_errors::ColorConfig;
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_lint_defs::Level;
use rustc_session::config::{
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CodegenRetagOptions, CoverageLevel,
CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
Externs, FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input,
InstrumentCoverage, InstrumentMcount, InstrumentMcountOpts, InstrumentXRay, LinkSelfContained,
LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options,
OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry,
Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
WasiExecModel, build_session_options, rustc_optgroups,
AnnotateMoves, AssumptionsOnBinders, AutoDiff, BranchProtection, CFGuard, Cfg,
CodegenRetagOptions, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat,
ErrorOutputType, ExternEntry, ExternLocation, Externs, FmtDebug, FunctionReturn,
IncrementalStateAssertion, InliningThreshold, Input, InstrumentCoverage, InstrumentMcount,
InstrumentMcountOpts, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, OutputType,
OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius,
ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
build_session_options, rustc_optgroups,
};
use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib};
Expand Down Expand Up @@ -950,7 +951,14 @@ fn test_assumptions_on_binders_enables_next_solver_globally() {
// `-Zassumptions-on-binders` alone enables the next solver globally.
let matches = optgroups().parse(&["-Zassumptions-on-binders".to_string()]).unwrap();
let opts = build_session_options(&mut early_dcx, &matches);
assert!(opts.unstable_opts.assumptions_on_binders);
assert_eq!(opts.unstable_opts.assumptions_on_binders, AssumptionsOnBinders::All);
assert_eq!(opts.unstable_opts.next_solver, globally);

// The minimal coroutine mode also requires the next solver globally.
let matches =
optgroups().parse(&["-Zassumptions-on-binders=min_coroutines".to_string()]).unwrap();
let opts = build_session_options(&mut early_dcx, &matches);
assert_eq!(opts.unstable_opts.assumptions_on_binders, AssumptionsOnBinders::MinCoroutines);
assert_eq!(opts.unstable_opts.next_solver, globally);

// Flag order must not matter when both `-Zassumptions-on-binders` and `-Znext-solver`
Expand All @@ -961,7 +969,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() {
] {
let matches = optgroups().parse(&args).unwrap();
let opts = build_session_options(&mut early_dcx, &matches);
assert!(opts.unstable_opts.assumptions_on_binders);
assert_eq!(opts.unstable_opts.assumptions_on_binders, AssumptionsOnBinders::All);
assert_eq!(opts.unstable_opts.next_solver, globally);
}

Expand All @@ -974,7 +982,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() {
] {
let matches = optgroups().parse(&args).unwrap();
let opts = build_session_options(&mut early_dcx, &matches);
assert!(opts.unstable_opts.assumptions_on_binders);
assert_eq!(opts.unstable_opts.assumptions_on_binders, AssumptionsOnBinders::All);
assert_eq!(opts.unstable_opts.next_solver, globally);
}
}
18 changes: 16 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2827,8 +2827,22 @@ impl<'tcx> TyCtxt<'tcx> {
|| self.sess.opts.unstable_opts.typing_mode_post_typeck_until_borrowck
}

pub fn assumptions_on_binders(self) -> bool {
self.sess.opts.unstable_opts.assumptions_on_binders
/// Whether any `-Zassumptions-on-binders` mode is enabled. Use this to gate
/// the shared machinery, e.g. tracking region constraints in the solver.
pub fn assumptions_on_binders_any(self) -> bool {
self.sess.opts.unstable_opts.assumptions_on_binders.any_is_enabled()
}

/// Whether the full `-Zassumptions-on-binders` mode is enabled, deducing
/// assumptions from every binder.
pub fn assumptions_on_binders_full(self) -> bool {
self.sess.opts.unstable_opts.assumptions_on_binders.is_full()
}

/// Whether `-Zassumptions-on-binders=min_coroutines` is enabled, deducing
/// assumptions only from coroutine-witness binders.
pub fn assumptions_on_binders_min_coroutines(self) -> bool {
self.sess.opts.unstable_opts.assumptions_on_binders.is_min_coroutines()
}

pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.features()
}

fn assumptions_on_binders(self) -> bool {
self.assumptions_on_binders()
fn assumptions_on_binders_any(self) -> bool {
self.assumptions_on_binders_any()
}

fn assumptions_on_binders_full(self) -> bool {
self.assumptions_on_binders_full()
}

fn assumptions_on_binders_min_coroutines(self) -> bool {
self.assumptions_on_binders_min_coroutines()
}

fn renormalize_rigid_aliases(self) -> bool {
Expand Down
36 changes: 21 additions & 15 deletions compiler/rustc_next_trait_solver/src/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,7 @@ where
let prev_universe = delegate.universe();
let universes_created_in_query = response.max_universe.index();
for _ in 0..universes_created_in_query {
let new_universe = delegate.create_next_universe();
if delegate.cx().assumptions_on_binders() {
// FIXME(-Zassumptions-on-binders): Remove this temporary workaround once
// opaque types no longer escape query responses with query-created placeholders.
// Region constraints involving query-created placeholders were handled inside
// the query. However, the placeholders can still escape in other response
// fields, such as opaque type constraints. To avoid triggering
// assertions, we explicitly insert empty assumptions for the
// recreated universes here.
delegate.insert_placeholder_assumptions(
new_universe,
Some(rustc_type_ir::region_constraint::Assumptions::empty()),
);
}
create_next_universe_with_placeholder_assumptions(delegate);
}

compute_query_response_instantiation_values_in_universe(
Expand All @@ -188,6 +175,25 @@ where
)
}

fn create_next_universe_with_placeholder_assumptions<D, I>(delegate: &D)
where
D: SolverDelegate<Interner = I>,
I: Interner,
{
let new_universe = delegate.create_next_universe();
if delegate.cx().assumptions_on_binders_any() {
// FIXME(-Zassumptions-on-binders): Remove this temporary workaround once opaque types no
// longer escape query responses with query-created placeholders. Region constraints
// involving query-created placeholders were handled inside the query, but placeholders can
// still escape in other response fields. These contextless universes use empty assumptions:
// they cannot discharge constraints, but allow them to propagate back to their source.
delegate.insert_placeholder_assumptions(
new_universe,
Some(rustc_type_ir::region_constraint::Assumptions::empty()),
);
}
}

fn compute_query_response_instantiation_values_in_universe<D, I, T>(
delegate: &D,
original_values: &[I::GenericArg],
Expand Down Expand Up @@ -591,7 +597,7 @@ where
// and the previous instantiation, extend `orig_values` for it.
let max_universe = prev_universe + state.max_universe.index();
while delegate.universe() < max_universe {
delegate.create_next_universe();
create_next_universe_with_placeholder_assumptions(delegate);
}
orig_values.extend(
state.value.var_values.var_values.as_slice()[orig_values.len()..]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_next_trait_solver/src/placeholder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ where
current_index: _,
} = replacer;

if infcx.cx().assumptions_on_binders() {
if infcx.cx().assumptions_on_binders_any() {
for (old, new) in old_universes.into_iter().zip(universe_indices.iter()) {
if let (None, Some(new)) = (old, new) {
// FIXME(-Zassumptions-on-binders): `replace_bound_vars` does not have enough
Expand Down
32 changes: 19 additions & 13 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use tracing::instrument;

use super::assembly::{Candidate, structural_traits};
use crate::delegate::SolverDelegate;
use crate::solve::eval_ctxt::ForallBinderKind;
use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, assembly,
};
Expand Down Expand Up @@ -267,19 +268,24 @@ where
structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?;

ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys| {
ecx.add_goals(
GoalSource::ImplWhereBound,
tys.into_iter().map(|ty| {
goal.with(
cx,
ty::ClauseKind::HostEffect(
goal.predicate.with_replaced_self_ty(cx, ty),
),
)
}),
)
})?;
ecx.enter_forall_with_assumptions(
constituent_tys,
goal.param_env,
ForallBinderKind::for_self_ty::<I>(self_ty),
|ecx, tys| {
ecx.add_goals(
GoalSource::ImplWhereBound,
tys.into_iter().map(|ty| {
goal.with(
cx,
ty::ClauseKind::HostEffect(
goal.predicate.with_replaced_self_ty(cx, ty),
),
)
}),
)
},
)?;

ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
Expand Down
28 changes: 24 additions & 4 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ pub mod fast_path;
mod probe;
mod solver_region_constraints;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(super) enum ForallBinderKind {
Other,
CoroutineWitness,
}

impl ForallBinderKind {
pub(super) fn for_self_ty<I: Interner>(self_ty: I::Ty) -> Self {
if matches!(self_ty.kind(), ty::CoroutineWitness(..)) {
Self::CoroutineWitness
} else {
Self::Other
}
}
}

/// The kind of goal we're currently proving.
///
/// This has effects on cycle handling handling and on how we compute
Expand Down Expand Up @@ -886,7 +902,7 @@ where
) -> QueryResultOrRerunNonErased<I> {
let Goal { param_env, predicate } = goal;
let kind = predicate.kind();
self.enter_forall_with_assumptions(kind, param_env, |ecx, kind| {
self.enter_forall_with_assumptions(kind, param_env, ForallBinderKind::Other, |ecx, kind| {
Ok(match kind {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)?
Expand Down Expand Up @@ -1285,11 +1301,15 @@ where
&mut self,
value: ty::Binder<I, T>,
param_env: I::ParamEnv,
binder_kind: ForallBinderKind,
f: impl FnOnce(&mut Self, T) -> U,
) -> U {
self.delegate.enter_forall_without_assumptions(value, |value| {
let u = self.delegate.universe();
let assumptions = if self.cx().assumptions_on_binders() {
let assumptions = if self.cx().assumptions_on_binders_full()
|| (self.cx().assumptions_on_binders_min_coroutines()
&& binder_kind == ForallBinderKind::CoroutineWitness)
{
self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env)
} else {
None
Expand Down Expand Up @@ -1533,7 +1553,7 @@ where
previous call to `try_evaluate_added_goals!`"
);

let goals_certainty = match self.delegate.cx().assumptions_on_binders() {
let goals_certainty = match self.delegate.cx().assumptions_on_binders_any() {
true => {
let certainty = self.eagerly_handle_placeholders()?;
certainty.and(goals_certainty)
Expand Down Expand Up @@ -1662,7 +1682,7 @@ where
// region constraints from an ambiguous nested goal. This is tested in both
// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and
// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`.
let region_constraints = if self.cx().assumptions_on_binders() {
let region_constraints = if self.cx().assumptions_on_binders_any() {
ExternalRegionConstraints::NextGen(if let Certainty::Yes = certainty {
let constraint = self.delegate.get_solver_region_constraint();
debug_assert_eq!(
Expand Down
Loading
Loading