eagerly compute sub_relations again

This commit is contained in:
lcnr
2025-08-27 10:03:47 +02:00
parent f099b241e2
commit 67965f817d
15 changed files with 152 additions and 111 deletions

View File

@@ -91,7 +91,6 @@ mod suggest;
pub mod need_type_info;
pub mod nice_region_error;
pub mod region;
pub mod sub_relations;
/// Makes a valid string literal from a string by escaping special characters (" and \),
/// unless they are already escaped.

View File

@@ -894,7 +894,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
use ty::{Infer, TyVar};
match (inner_ty.kind(), target_ty.kind()) {
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid)
self.tecx.sub_root_var(a_vid) == self.tecx.sub_root_var(b_vid)
}
_ => false,
}

View File

@@ -1,81 +0,0 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::undo_log::NoUndo;
use rustc_data_structures::unify as ut;
use rustc_middle::ty;
use crate::infer::InferCtxt;
#[derive(Debug, Copy, Clone, PartialEq)]
struct SubId(u32);
impl ut::UnifyKey for SubId {
type Value = ();
#[inline]
fn index(&self) -> u32 {
self.0
}
#[inline]
fn from_index(i: u32) -> SubId {
SubId(i)
}
fn tag() -> &'static str {
"SubId"
}
}
/// When reporting ambiguity errors, we sometimes want to
/// treat all inference vars which are subtypes of each
/// others as if they are equal. For this case we compute
/// the transitive closure of our subtype obligations here.
///
/// E.g. when encountering ambiguity errors, we want to suggest
/// specifying some method argument or to add a type annotation
/// to a local variable. Because subtyping cannot change the
/// shape of a type, it's fine if the cause of the ambiguity error
/// is only related to the suggested variable via subtyping.
///
/// Even for something like `let x = returns_arg(); x.method();` the
/// type of `x` is only a supertype of the argument of `returns_arg`. We
/// still want to suggest specifying the type of the argument.
#[derive(Default)]
pub struct SubRelations {
map: FxHashMap<ty::TyVid, SubId>,
table: ut::UnificationTableStorage<SubId>,
}
impl SubRelations {
fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId {
let root_vid = infcx.root_var(vid);
*self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(()))
}
pub fn add_constraints<'tcx>(
&mut self,
infcx: &InferCtxt<'tcx>,
obls: impl IntoIterator<Item = ty::Predicate<'tcx>>,
) {
for p in obls {
let (a, b) = match p.kind().skip_binder() {
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
(a, b)
}
ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
_ => continue,
};
match (a.kind(), b.kind()) {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
let a = self.get_id(infcx, a_vid);
let b = self.get_id(infcx, b_vid);
self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap();
}
_ => continue,
}
}
}
pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool {
let a = self.get_id(infcx, a);
let b = self.get_id(infcx, b);
self.table.with_log(&mut NoUndo).unioned(a, b)
}
}

View File

@@ -7,8 +7,6 @@ use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty};
use crate::error_reporting::infer::sub_relations;
pub mod infer;
pub mod traits;
@@ -21,7 +19,6 @@ pub mod traits;
/// methods which should not be used during the happy path.
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub fallback_has_occurred: bool,
@@ -38,7 +35,6 @@ impl<'tcx> InferCtxt<'tcx> {
fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
TypeErrCtxt {
infcx: self,
sub_relations: Default::default(),
typeck_results: None,
fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig),

View File

@@ -139,10 +139,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&self,
mut errors: Vec<FulfillmentError<'tcx>>,
) -> ErrorGuaranteed {
self.sub_relations
.borrow_mut()
.add_constraints(self, errors.iter().map(|e| e.obligation.predicate));
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
goal: Goal<'tcx, ty::Predicate<'tcx>>,

View File

@@ -126,13 +126,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
}
ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, .. })
| ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
if self.shallow_resolve(a).is_ty_var() && self.shallow_resolve(b).is_ty_var() {
// FIXME: We also need to register a subtype relation between these vars
// when those are added, and if they aren't in the same sub root then
// we should mark this goal as `has_changed`.
Some(Certainty::AMBIGUOUS)
} else {
None
match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
self.sub_ty_vids_raw(a_vid, b_vid);
Some(Certainty::AMBIGUOUS)
}
_ => None,
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => {