Skip to content
Draft
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
402 changes: 395 additions & 7 deletions compiler/rustc_borrowck/src/lib.rs

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.scc_values.placeholders_contained_in(scc)
}

/// Returns `true` if the SCC value of `sup_scc` is a superset of `sub_scc`'s
/// value across all components (CFG points, universals, placeholders).
pub(crate) fn scc_values_contain(
&self,
sup_scc: ConstraintSccIndex,
sub_scc: ConstraintSccIndex,
) -> bool {
if sup_scc == sub_scc {
return true;
}
self.scc_values.contains_region_values(sup_scc, sub_scc)
}

/// Performs region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
Expand Down Expand Up @@ -1862,6 +1875,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&self.constraint_sccs
}

/// Returns the universal regions outlived by the given SCC.
pub fn universal_regions_outlived_by_scc(
&self,
scc: ConstraintSccIndex,
) -> impl Iterator<Item = RegionVid> {
self.scc_values.universal_regions_outlived_by(scc)
}

/// Returns the representative `RegionVid` for a given SCC.
/// See `RegionTracker` for how a region variable ID is chosen.
///
Expand Down
36 changes: 36 additions & 0 deletions compiler/rustc_borrowck/src/region_infer/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,42 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> {
}
}

/// Returns `true` if `sup_region`'s value is a superset of `sub_region`'s
/// value across ALL components: CFG points, free (universal) regions, and
/// placeholders. This is the full outlives check for NLL region values.
pub(crate) fn contains_region_values(&self, sup_region: N, sub_region: N) -> bool {
// Short-circuit on CFG points first.
if !self.contains_points(sup_region, sub_region) {
return false;
}

// Check universal (free) regions.
if let Some(sub_row) = self.free_regions.row(sub_region)
&& !sub_row.is_empty()
{
let Some(sup_row) = self.free_regions.row(sup_region) else {
return false;
};
if !sup_row.superset(sub_row) {
return false;
}
}

// Check placeholders.
if let Some(sub_row) = self.placeholders.row(sub_region)
&& !sub_row.is_empty()
{
let Some(sup_row) = self.placeholders.row(sup_region) else {
return false;
};
if !sup_row.superset(sub_row) {
return false;
}
}

true
}

/// Returns the locations contained within a given region `r`.
pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
self.points
Expand Down
17 changes: 14 additions & 3 deletions compiler/rustc_borrowck/src/root_cx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub(super) struct BorrowCheckRootCtxt<'diag, 'tcx: 'diag> {
collect_region_constraints_results:
FxIndexMap<LocalDefId, CollectRegionConstraintsResult<'tcx>>,
propagated_borrowck_results: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
pub(super) coroutine_nll_constraints:
FxIndexMap<LocalDefId, rustc_middle::mir::CoroutineNllOutlives<'tcx>>,
tainted_by_errors: &'diag Cell<Option<ErrorGuaranteed>>,
/// This should be `None` during normal compilation. See [`crate::consumers`] for more
/// information on how this is used.
Expand All @@ -62,6 +64,7 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
unconstrained_hidden_type_errors: Default::default(),
collect_region_constraints_results: Default::default(),
propagated_borrowck_results: Default::default(),
coroutine_nll_constraints: Default::default(),
tainted_by_errors,
consumer,
}
Expand All @@ -79,6 +82,12 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
}

pub(super) fn hidden_types(
&self,
) -> &FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>> {
&self.hidden_types
}

pub(super) fn used_mut_upvars(
&self,
nested_body_def_id: LocalDefId,
Expand All @@ -88,12 +97,14 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {

pub(super) fn finalize(
self,
) -> Result<&'tcx FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>, ErrorGuaranteed>
{
) -> Result<&'tcx rustc_middle::mir::BorrowCheckResult<'tcx>, ErrorGuaranteed> {
if let Some(guar) = self.tainted_by_errors.get() {
Err(guar)
} else {
Ok(self.tcx.arena.alloc(self.hidden_types))
Ok(self.tcx.arena.alloc(rustc_middle::mir::BorrowCheckResult {
opaque_types: self.hidden_types,
coroutine_nll_constraints: self.coroutine_nll_constraints,
}))
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ fn retry_codegen_mode_with_postanalysis<'tcx, K: TypeVisitable<TyCtxt<'tcx>>, V>
ty::TypingMode::Coherence
| ty::TypingMode::Typeck { .. }
| ty::TypingMode::PostTypeckUntilBorrowck { .. }
| ty::TypingMode::BorrowckPendingScc { .. }
| ty::TypingMode::PostBorrowck { .. }
| ty::TypingMode::Reflection
| ty::TypingMode::PostAnalysis => {}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn assert_typing_mode(typing_mode: ty::TypingMode<'_>) {
| ty::TypingMode::Typeck { .. }
| ty::TypingMode::Reflection
| ty::TypingMode::PostTypeckUntilBorrowck { .. }
| ty::TypingMode::BorrowckPendingScc { .. }
| ty::TypingMode::PostBorrowck { .. } => bug!(
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment on `assert_typing_mode` for more details."
),
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ fn best_definition_site_of_opaque<'tcx>(
.tcx
.mir_borrowck(item_def_id)
.ok()
.and_then(|opaque_types| opaque_types.get(&self.opaque_def_id))
.and_then(|result| result.opaque_types.get(&self.opaque_def_id))
{
ControlFlow::Break((hidden_ty.span, item_def_id))
} else {
Expand Down Expand Up @@ -2271,7 +2271,13 @@ pub(super) fn check_coroutine_obligations(

debug!(?typeck_results.coroutine_stalled_predicates);

let mode = if tcx.next_trait_solver_globally() {
let mode = if tcx.dxf() {
// When dxf is active and called from mir_borrowck, NLL data
// is not yet available.
// Use BorrowckPendingScc to stall coroutine auto-trait goals
// as pending.
TypingMode::borrowck_pending_scc(tcx, def_id)
} else if tcx.next_trait_solver_globally() {
// This query is conceptually between HIR typeck and
// MIR borrowck. We use the opaque types defined by HIR
// and ignore region constraints.
Expand All @@ -2291,7 +2297,14 @@ pub(super) fn check_coroutine_obligations(
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
}

let errors = ocx.evaluate_obligations_error_on_ambiguity();
// In BorrowckPendingScc mode, coroutine auto-trait goals are expected
// to stall awaiting NLL data (StalledOnCoroutines::Yes).
// Evaluate without treating ambiguity as a hard error.
let errors = if mode.is_borrowck_pending_scc() {
ocx.try_evaluate_obligations()
} else {
ocx.evaluate_obligations_error_on_ambiguity()
};
debug!(?errors);
if let TraitErrors::HasErrors(errors) = errors {
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2294,7 +2294,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// regular WF checking
ty::ClauseKind::WellFormed(..)
// Unstable feature goals cannot be proven in an empty environment so skip them
| ty::ClauseKind::UnstableFeature(..) => continue,
| ty::ClauseKind::UnstableFeature(..)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..) => continue,
_ => {}
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/clauses_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ pub(super) fn assert_only_contains_clauses_from<'tcx>(
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::UnstableFeature(_)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..)
| ty::ClauseKind::ConstEvaluatable(_) => {
bug!(
"unexpected non-`Self` predicate when computing \
Expand Down Expand Up @@ -824,6 +825,7 @@ pub(super) fn assert_only_contains_clauses_from<'tcx>(
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::UnstableFeature(_)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..)
| ty::ClauseKind::HostEffect(..) => {
bug!(
"unexpected non-`Self` predicate when computing \
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
}
DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(item_def_id) {
Err(guar) => self.insert_found(ty::DefinitionSiteHiddenType::new_error(tcx, guar)),
Ok(hidden_types) => {
if let Some(&hidden_type) = hidden_types.get(&self.def_id) {
Ok(result) => {
if let Some(&hidden_type) = result.opaque_types.get(&self.def_id) {
debug!(?hidden_type, "found constraint");
self.insert_found(hidden_type);
} else if let Err(guar) =
Expand Down Expand Up @@ -269,8 +269,8 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
}
}
DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) {
Ok(hidden_types) => {
if let Some(hidden_ty) = hidden_types.get(&def_id) {
Ok(result) => {
if let Some(hidden_ty) = result.opaque_types.get(&def_id) {
hidden_ty.ty
} else {
let hir_ty = tcx.type_of_opaque_hir_typeck(def_id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ fn trait_specialization_kind<'tcx>(
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::UnstableFeature(_)
| ty::ClauseKind::HostEffect(..) => None,
| ty::ClauseKind::HostEffect(..)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..) => None,
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/outlives/explicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ impl<'tcx> ExplicitClausesMap<'tcx> {
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::UnstableFeature(_)
| ty::ClauseKind::HostEffect(..) => {}
| ty::ClauseKind::HostEffect(..)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..) => {}
}
}

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,16 +726,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::TypingMode::Coherence
| ty::TypingMode::Reflection
| ty::TypingMode::PostTypeckUntilBorrowck { .. }
| ty::TypingMode::BorrowckPendingScc { .. }
| ty::TypingMode::PostBorrowck { .. }
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen => {
bug!()
}
};

if defining_opaque_types_and_generators
.iter()
.any(|def_id| self.tcx.is_coroutine(def_id.to_def_id()))
if self.tcx.sess.opts.unstable_opts.dxf
|| defining_opaque_types_and_generators
.iter()
.any(|def_id| self.tcx.is_coroutine(def_id.to_def_id()))
{
self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(
self.fulfillment_cx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_))
| ty::PredicateKind::Clause(ty::ClauseKind::CoroutineWitnessRegionConstraints(..))
| ty::PredicateKind::Ambiguous => false,
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::UnstableFeature(_)
| ty::ClauseKind::HostEffect(..) => None,
| ty::ClauseKind::HostEffect(..)
| ty::ClauseKind::CoroutineWitnessRegionConstraints(..) => None,
}
});

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
ty::TypingMode::Coherence
| ty::TypingMode::Reflection
| ty::TypingMode::PostTypeckUntilBorrowck { .. }
| ty::TypingMode::BorrowckPendingScc { .. }
| ty::TypingMode::PostBorrowck { .. }
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen => {
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
&self,
u: ty::UniverseIndex,
) -> Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>> {
self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().as_ref().cloned()
self.placeholder_assumptions_for_next_solver
.borrow()
.get(&u)
.and_then(|v| v.as_ref().cloned())
}

fn get_solver_region_constraint(
Expand Down Expand Up @@ -426,6 +429,14 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
ty::ProvisionalHiddenType { span, ty: hidden_ty },
)
}

fn lookup_hidden_type_in_storage(
&self,
opaque_type_key: &ty::OpaqueTypeKey<'tcx>,
) -> Option<Ty<'tcx>> {
self.lookup_hidden_type_in_storage(opaque_type_key)
}

fn add_duplicate_opaque_type(
&self,
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ impl<'tcx> Drop for InferCtxt<'tcx> {
| TypingMode::Codegen => {}
// In erased mode, the opaque type storage is always empty
TypingMode::ErasedNotCoherence(..) => {}
TypingMode::PostTypeckUntilBorrowck { .. } => {
TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::BorrowckPendingScc { .. } => {
if !self.considering_regions {
return;
}
Expand Down Expand Up @@ -1176,9 +1176,11 @@ impl<'tcx> InferCtxt<'tcx> {
debug_assert!(!self.next_trait_solver());
match self.typing_mode_raw().assert_not_erased() {
TypingMode::Typeck { defining_opaque_types_and_generators: defining_opaque_types }
| TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
}
| TypingMode::PostTypeckUntilBorrowck { defining_opaque_types, .. }
| TypingMode::BorrowckPendingScc {
defining_opaque_types_and_generators: defining_opaque_types,
..
} => id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)),
// FIXME(#132279): This function is quite weird in post-analysis
// and post-borrowck analysis mode. We may need to modify its uses
// to support PostBorrowck in the old solver as well.
Expand Down Expand Up @@ -1555,9 +1557,8 @@ impl<'tcx> InferCtxt<'tcx> {
// errors and fail to reveal opaques while inside of bodies. We should rename this
// function and require explicit comments on all use-sites in the future.
ty::TypingMode::Typeck { defining_opaque_types_and_generators: _ }
| ty::TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } => {
TypingMode::non_body_analysis()
}
| ty::TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _, .. }
| ty::TypingMode::BorrowckPendingScc { .. } => TypingMode::non_body_analysis(),
mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowck { .. }
| ty::TypingMode::PostAnalysis
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty)
}

/// Look up a previously registered hidden type for the given opaque type key.
/// Returns `None` if no hidden type has been registered.
/// This is a read-only operation — it does not modify storage.
pub fn lookup_hidden_type_in_storage(
&self,
opaque_type_key: &OpaqueTypeKey<'tcx>,
) -> Option<Ty<'tcx>> {
self.inner.borrow().opaque_type_storage.get(opaque_type_key)
}

/// Insert a hidden type into the opaque type storage, equating it
/// with any previous entries if necessary.
///
Expand Down Expand Up @@ -254,7 +264,8 @@ impl<'tcx> InferCtxt<'tcx> {
);
}
}
ty::TypingMode::PostTypeckUntilBorrowck { .. } => {
ty::TypingMode::PostTypeckUntilBorrowck { .. }
| ty::TypingMode::BorrowckPendingScc { .. } => {
let prev = self
.inner
.borrow_mut()
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_infer/src/infer/opaque_types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
opaque_types.is_empty() && duplicate_entries.is_empty()
}

/// Look up a previously registered hidden type for the given opaque type key.
/// Returns `None` if no hidden type has been registered for this key.
pub fn get(&self, key: &OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
self.opaque_types.get(key).map(|entry| entry.ty)
}

pub(crate) fn take_opaque_types(
&mut self,
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)> {
Expand Down
Loading
Loading