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
11 changes: 3 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,14 +478,9 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
let errci = ErrorConstraintInfo { fr, outlived_fr, category, span };

let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::SolverRegionConstraint(span), _, _) => {
let mut d = self.dcx().struct_span_err(
span,
"unsatisfied lifetime constraint from -Zassumptions-on-binders :3",
);
d.note("meoow :c");
d
}
(ConstraintCategory::SolverRegionConstraint(span), _, _) => self
.dcx()
.struct_span_err(span, "higher-ranked lifetime bound could not be satisfied"),
(ConstraintCategory::Return(kind), true, false)
if self.regioncx.is_closure_fn_mut(fr) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
GenericArgKind::Lifetime(r1) => {
let r1_vid = self.to_region_vid(r1);
let r2_vid = self.to_region_vid(r2);
self.add_outlives(r1_vid, r2_vid, constraint_category);
self.add_outlives(r1_vid, r2_vid, constraint_category, self.span);
}

GenericArgKind::Type(mut t1) => {
Expand Down Expand Up @@ -221,6 +221,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
sup: ty::RegionVid,
sub: ty::RegionVid,
category: ConstraintCategory<'tcx>,
span: Span,
) {
let category = match self.category {
ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
Expand All @@ -229,7 +230,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
self.constraints.outlives_constraints.push(OutlivesConstraint {
locations: self.locations,
category,
span: self.span,
span,
sub,
sup,
variance_info: ty::VarianceDiagInfo::default(),
Expand All @@ -246,14 +247,14 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
fn push_sub_region_constraint(
&mut self,
_origin: SubregionOrigin<'tcx>,
origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
constraint_category: ConstraintCategory<'tcx>,
) {
let b = self.to_region_vid(b);
let a = self.to_region_vid(a);
self.add_outlives(b, a, constraint_category);
self.add_outlives(b, a, constraint_category, origin.span());
}

fn push_verify(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ pub(crate) fn type_check<'tcx>(
&mut converter,
typeck.known_type_outlives_obligations,
universal_region_relations.outlives.clone(),
infcx.tcx.def_span(infcx.root_def_id),
);
}

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 @@ -64,20 +64,21 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
fn get_solver_region_constraint(
&self,
) -> rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>> {
self.inner.borrow().solver_region_constraint_storage.get_constraint()
self.inner.borrow().solver_region_constraint_storage.get_unspanned_constraint()
}

fn overwrite_solver_region_constraint(
&self,
constraint: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
span: Span,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;

use crate::infer::UndoLog;
let old_constraint = inner.solver_region_constraint_storage.get_constraint();
inner.undo_log.push(UndoLog::OverwriteSolverRegionConstraint { old_constraint });
inner.solver_region_constraint_storage.overwrite_solver_region_constraint(constraint);
inner.solver_region_constraint_storage.overwrite(constraint, span);
}

fn universe_of_ty(&self, vid: ty::TyVid) -> Option<ty::UniverseIndex> {
Expand Down Expand Up @@ -331,14 +332,15 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
fn register_solver_region_constraint(
&self,
c: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
span: Span,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;

use crate::infer::UndoLog;
let previous_was_and = inner.solver_region_constraint_storage.is_and();
inner.undo_log.push(UndoLog::PushSolverRegionConstraint { previous_was_and });
inner.solver_region_constraint_storage.push(c);
inner.solver_region_constraint_storage.push(c, span);
}

fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
Expand Down
60 changes: 4 additions & 56 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ pub mod region_constraints;
pub mod relate;
pub mod resolve;
pub(crate) mod snapshot;
mod solver_region_constraints;
mod type_variable;
mod unify_key;

pub(crate) use solver_region_constraints::SolverRegionConstraint;
use solver_region_constraints::SolverRegionConstraintStorage;

/// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper
/// around `PredicateObligations<'tcx>`, but it has one important property:
/// because `InferOk` is marked with `#[must_use]`, if you have a method
Expand Down Expand Up @@ -1809,62 +1813,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

type SolverRegionConstraint<'tcx> =
rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>;

#[derive(Clone, Debug)]
struct SolverRegionConstraintStorage<'tcx>(SolverRegionConstraint<'tcx>);

impl<'tcx> SolverRegionConstraintStorage<'tcx> {
fn new() -> Self {
SolverRegionConstraintStorage(SolverRegionConstraint::And(Box::new([])))
}

fn get_constraint(&self) -> SolverRegionConstraint<'tcx> {
self.0.clone()
}

fn is_and(&self) -> bool {
self.0.is_and()
}

fn pop(&mut self, previous_was_and: bool) -> Option<SolverRegionConstraint<'tcx>> {
match &mut self.0 {
SolverRegionConstraint::And(and) => {
let mut and = core::mem::take(and).into_iter().collect::<Vec<_>>();
let popped = and.pop()?;
if previous_was_and {
self.0 = SolverRegionConstraint::And(and.into_boxed_slice());
} else {
assert_eq!(and.len(), 1);
self.0 = and.pop().unwrap();
}
Some(popped)
}
_ => unreachable!(),
}
}

#[instrument(level = "debug")]
fn push(&mut self, constraint: SolverRegionConstraint<'tcx>) {
match core::mem::replace(&mut self.0, SolverRegionConstraint::new_true()) {
SolverRegionConstraint::And(and) => {
let and =
and.into_iter().chain([constraint]).collect::<Vec<_>>().into_boxed_slice();
self.0 = SolverRegionConstraint::And(and);
}
previous => {
self.0 = SolverRegionConstraint::And(Box::new([previous, constraint]));
}
}
}

#[instrument(level = "debug", skip(self))]
fn overwrite_solver_region_constraint(&mut self, constraint: SolverRegionConstraint<'tcx>) {
self.0 = constraint;
}
}

/// Returns unresolved root variables from `table`, according to `is_unresolved`.
fn unresolved_root_variables_of<V: UnifyKey>(
mut table: UnificationTable<'_, '_, V>,
Expand Down
32 changes: 15 additions & 17 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,12 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn destructure_solver_region_constraints_for_regionck(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
span: Span,
) {
let assumptions = rustc_type_ir::region_constraint::Assumptions::new(
outlives_env.known_type_outlives().into_iter().cloned().collect(),
outlives_env.free_region_map().relation.clone(),
);
self.destructure_solver_region_constraints(assumptions, self, span);
self.destructure_solver_region_constraints(assumptions, self);
}

pub fn destructure_solver_region_constraints_for_borrowck(
Expand All @@ -230,28 +229,23 @@ impl<'tcx> InferCtxt<'tcx> {
conversion: impl TypeOutlivesDelegate<'tcx>,
known_type_outlives: &[PolyTypeOutlivesClause<'tcx>],
region_outlives: TransitiveRelation<RegionVid>,
span: Span,
) {
let assumptions = rustc_type_ir::region_constraint::Assumptions::new(
known_type_outlives.into_iter().cloned().collect(),
region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(),
);
self.destructure_solver_region_constraints(assumptions, conversion, span);
self.destructure_solver_region_constraints(assumptions, conversion);
}

#[instrument(level = "debug", skip(self, conversion))]
pub fn destructure_solver_region_constraints(
&self,
assumptions: rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>,
mut conversion: impl TypeOutlivesDelegate<'tcx>,
span: Span,
) {
assert!(self.tcx.assumptions_on_binders());
assert!(self.next_trait_solver());

let origin = SubregionOrigin::SolverRegionConstraint(span);
let category = origin.to_constraint_category();

let constraint = self.inner.borrow().solver_region_constraint_storage.get_constraint();
debug!(?constraint);
let constraint =
Expand All @@ -269,16 +263,20 @@ impl<'tcx> InferCtxt<'tcx> {
use rustc_type_ir::region_constraint::RegionConstraint::*;

match c {
Ambiguity => {
self.dcx().err("unable to satisfy constraints involving placeholders due to unknown implied bounds");
Ambiguity(span) => {
self.dcx()
.struct_span_err(
span,
"unable to satisfy constraints involving placeholders due to unknown implied bounds",
)
.emit();
}
RegionOutlives(a, b) => {
RegionOutlives(a, b, span) => {
let origin = SubregionOrigin::SolverRegionConstraint(span);
let category = origin.to_constraint_category();
conversion.push_sub_region_constraint(
origin.clone(),
// we flip these because regionck is silly :>
b,
a,
category,
origin, // we flip these because regionck is silly :>
b, a, category,
);
}
// FIXME(-Zassumptions-on-binders): actually implement OR as an OR
Expand Down Expand Up @@ -306,7 +304,7 @@ impl<'tcx> InferCtxt<'tcx> {
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");

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

// Must loop since the process of normalizing may itself register region obligations.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_infer/src/infer/snapshot/undo_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
);
}
UndoLog::OverwriteSolverRegionConstraint { old_constraint } => {
self.solver_region_constraint_storage
.overwrite_solver_region_constraint(old_constraint);
self.solver_region_constraint_storage.overwrite_spanned(old_constraint);
}
UndoLog::PushTypeOutlivesConstraint => {
let popped = self.region_obligations.pop();
Expand Down
77 changes: 77 additions & 0 deletions compiler/rustc_infer/src/infer/solver_region_constraints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
use rustc_type_ir::region_constraint::{
RegionConstraint as UnspannedRegionConstraint, SpannedRegionConstraint,
};
use tracing::instrument;

pub(crate) type SolverRegionConstraint<'tcx> = SpannedRegionConstraint<TyCtxt<'tcx>>;

#[derive(Clone, Debug)]
pub(crate) struct SolverRegionConstraintStorage<'tcx>(SolverRegionConstraint<'tcx>);

impl<'tcx> SolverRegionConstraintStorage<'tcx> {
pub(crate) fn new() -> Self {
Self(SolverRegionConstraint::And(Box::new([])))
}

pub(crate) fn get_constraint(&self) -> SolverRegionConstraint<'tcx> {
self.0.clone()
}

pub(crate) fn get_unspanned_constraint(&self) -> UnspannedRegionConstraint<TyCtxt<'tcx>> {
self.0.clone().without_spans()
}

pub(crate) fn is_and(&self) -> bool {
self.0.is_and()
}

pub(crate) fn pop(&mut self, previous_was_and: bool) -> Option<SolverRegionConstraint<'tcx>> {
match &mut self.0 {
SolverRegionConstraint::And(and) => {
let mut and = core::mem::take(and).into_vec();
let popped = and.pop()?;
if previous_was_and {
self.0 = SolverRegionConstraint::And(and.into_boxed_slice());
} else {
assert_eq!(and.len(), 1);
self.0 = and.pop().unwrap();
}
Some(popped)
}
_ => unreachable!(),
}
}

#[instrument(level = "debug")]
pub(crate) fn push(&mut self, constraint: UnspannedRegionConstraint<TyCtxt<'tcx>>, span: Span) {
let constraint = constraint.with_span(span);
match core::mem::replace(&mut self.0, SolverRegionConstraint::new_true()) {
SolverRegionConstraint::And(and) => {
let and =
and.into_iter().chain([constraint]).collect::<Vec<_>>().into_boxed_slice();
self.0 = SolverRegionConstraint::And(and);
}
previous => {
self.0 = SolverRegionConstraint::And(Box::new([previous, constraint]));
}
}
}

#[instrument(level = "debug", skip(self))]
pub(crate) fn overwrite(
&mut self,
constraint: UnspannedRegionConstraint<TyCtxt<'tcx>>,
span: Span,
) {
self.overwrite_spanned(constraint.with_span(span));
}

pub(crate) fn overwrite_spanned(&mut self, constraint: SolverRegionConstraint<'tcx>) {
self.0 = constraint;
}
}

#[cfg(test)]
mod tests;
Loading