Skip to content

[for errs] perf run sub_relations change #140480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
7 changes: 0 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
use rustc_trait_selection::error_reporting::TypeErrCtxt;
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};

use crate::coercion::DynamicCoerceMany;
Expand Down Expand Up @@ -177,14 +176,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
let mut sub_relations = SubRelations::default();
sub_relations.add_constraints(
self,
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
);
TypeErrCtxt {
infcx: &self.infcx,
sub_relations: RefCell::new(sub_relations),
typeck_results: Some(self.typeck_results.borrow()),
fallback_has_occurred: self.fallback_has_occurred.get(),
normalize_fn_sig: Box::new(|fn_sig| {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
debug!("pick_all_method: step={:?}", step);
// skip types that are from a type error or that would require dereferencing
// a raw pointer
!step.self_ty.references_error() && !step.from_unsafe_deref
!step.self_ty.value.references_error() && !step.from_unsafe_deref
})
.find_map(|step| {
let InferOk { value: self_ty, obligations: _ } = self
Expand Down
22 changes: 1 addition & 21 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_infer::traits::solve::Goal;
use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::{
Expand Down Expand Up @@ -513,15 +512,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
self.typeck_results.user_provided_types_mut().extend(
fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| {
let hir_id = HirId { owner: common_hir_owner, local_id };

if cfg!(debug_assertions) && c_ty.has_infer() {
span_bug!(
hir_id.to_span(self.fcx.tcx),
"writeback: `{:?}` has inference variables",
c_ty
);
};

(hir_id, *c_ty)
}),
);
Expand All @@ -532,17 +522,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);

self.typeck_results.user_provided_sigs.extend_unord(
fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
if cfg!(debug_assertions) && c_sig.has_infer() {
span_bug!(
self.fcx.tcx.def_span(def_id),
"writeback: `{:?}` has inference variables",
c_sig
);
};

(def_id, *c_sig)
}),
fcx_typeck_results.user_provided_sigs.items().map(|(def_id, c_sig)| (*def_id, *c_sig)),
);
}

Expand Down
23 changes: 6 additions & 17 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ use tracing::debug;

use crate::infer::InferCtxt;
use crate::infer::canonical::{
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind,
OriginalQueryValues,
Canonical, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
};

impl<'tcx> InferCtxt<'tcx> {
Expand Down Expand Up @@ -368,9 +367,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
ui = ty::UniverseIndex::ROOT;
}
self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
},
CanonicalVarInfo { kind: CanonicalVarKind::Ty(ui) },
t,
)
}
Expand All @@ -382,21 +379,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t,
)
self.canonicalize_ty_var(CanonicalVarInfo { kind: CanonicalVarKind::Int }, t)
}
}
ty::Infer(ty::FloatVar(vid)) => {
let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t,
)
self.canonicalize_ty_var(CanonicalVarInfo { kind: CanonicalVarKind::Float }, t)
}
}

Expand Down Expand Up @@ -690,12 +681,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
.iter()
.map(|v| CanonicalVarInfo {
kind: match v.kind {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
CanonicalVarKind::Int | CanonicalVarKind::Float => {
return *v;
}
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
}
CanonicalVarKind::Ty(u) => CanonicalVarKind::Ty(reverse_universe_map[&u]),
CanonicalVarKind::Region(u) => {
CanonicalVarKind::Region(reverse_universe_map[&u])
}
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_infer/src/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,9 @@ impl<'tcx> InferCtxt<'tcx> {
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> GenericArg<'tcx> {
match cv_info.kind {
CanonicalVarKind::Ty(ty_kind) => {
let ty = match ty_kind {
CanonicalTyVarKind::General(ui) => {
self.next_ty_var_in_universe(span, universe_map(ui))
}

CanonicalTyVarKind::Int => self.next_int_var(),

CanonicalTyVarKind::Float => self.next_float_var(),
};
ty.into()
}
CanonicalVarKind::Ty(ui) => self.next_ty_var_in_universe(span, universe_map(ui)).into(),
CanonicalVarKind::Int => self.next_int_var().into(),
CanonicalVarKind::Float => self.next_float_var().into(),

CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
let universe_mapped = universe_map(universe);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().type_variables().equate(a, b);
}

fn sub_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
self.inner.borrow_mut().type_variables().sub(a, b);
}

fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) {
self.inner.borrow_mut().int_unification_table().union(a, b);
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ impl<'tcx> InferCtxt<'tcx> {
let r_b = self.shallow_resolve(predicate.skip_binder().b);
match (r_a.kind(), r_b.kind()) {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
self.inner.borrow_mut().type_variables().sub(a_vid, b_vid);
return Err((a_vid, b_vid));
}
_ => {}
Expand Down Expand Up @@ -1065,6 +1066,10 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().type_variables().root_var(var)
}

pub fn sub_root_var(&self, var: ty::TyVid) -> ty::TyVid {
self.inner.borrow_mut().type_variables().sub_root_var(var)
}

pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
self.inner.borrow_mut().const_unification_table().find(var).vid
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/relate/generalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
let origin = inner.type_variables().var_origin(vid);
let new_var_id =
inner.type_variables().new_var(self.for_universe, origin);
// Record that `vid` and `new_var_id` have to be subtypes
// of each other. This is currently only used for diagnostics.
// To see why, see the docs in the `type_variables` module.
inner.type_variables().sub(vid, new_var_id);
// If we're in the new solver and create a new inference
// variable inside of an alias we eagerly constrain that
// inference variable to prevent unexpected ambiguity errors.
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/snapshot/undo_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Snapshot<'tcx> {
#[derive(Clone)]
pub(crate) enum UndoLog<'tcx> {
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
TypeVariables(type_variable::UndoLog<'tcx>),
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
Expand All @@ -44,7 +44,9 @@ macro_rules! impl_from {
impl_from! {
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),

TypeVariables(type_variable::UndoLog<'tcx>),
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
TypeVariables(sv::UndoLog<ut::Delegate<ty::TyVid>>),
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),

Expand Down
79 changes: 76 additions & 3 deletions compiler/rustc_infer/src/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,33 @@ use tracing::debug;

use crate::infer::InferCtxtUndoLogs;

impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
self.eq_relations.reverse(undo)
/// Represents a single undo-able action that affects a type inference variable.
#[derive(Clone)]
pub(crate) enum UndoLog<'tcx> {
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
}

/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
UndoLog::EqRelation(l)
}
}

/// Convert from a specific kind of undo to the more general UndoLog
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
UndoLog::SubRelation(l)
}
}

impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
fn reverse(&mut self, undo: UndoLog<'tcx>) {
match undo {
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
}
}
}

Expand All @@ -27,6 +51,24 @@ pub(crate) struct TypeVariableStorage<'tcx> {
/// constraint `?X == ?Y`. This table also stores, for each key,
/// the known value.
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,

/// Only used by `-Znext-solver` andfor diagnostics.
///
/// 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.
sub_relations: ut::UnificationTableStorage<ty::TyVid>,
}

pub(crate) struct TypeVariableTable<'a, 'tcx> {
Expand Down Expand Up @@ -109,6 +151,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
debug_assert!(self.probe(a).is_unknown());
debug_assert!(self.probe(b).is_unknown());
self.eq_relations().union(a, b);
self.sub_relations().union(a, b);
}

/// Records that `a <: b`, depending on `dir`.
///
/// Precondition: neither `a` nor `b` are known.
pub(crate) fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
debug_assert!(self.probe(a).is_unknown());
debug_assert!(self.probe(b).is_unknown());
self.sub_relations().union(a, b);
}

/// Instantiates `vid` with the type `ty`.
Expand Down Expand Up @@ -142,6 +194,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
origin: TypeVariableOrigin,
) -> ty::TyVid {
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });

let sub_key = self.sub_relations().new_key(());
debug_assert_eq!(eq_key.vid, sub_key);

let index = self.storage.values.push(TypeVariableData { origin });
debug_assert_eq!(eq_key.vid, index);

Expand All @@ -164,6 +220,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
self.eq_relations().find(vid).vid
}

/// Returns the "root" variable of `vid` in the `sub_relations`
/// equivalence table. All type variables that have been are
/// related via equality or subtyping will yield the same root
/// variable (per the union-find algorithm), so `sub_root_var(a)
/// == sub_root_var(b)` implies that:
/// ```text
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
/// ```
pub(crate) fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
self.sub_relations().find(vid)
}

/// Retrieves the type to which `vid` has been instantiated, if
/// any.
pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
Expand All @@ -181,6 +249,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
self.storage.eq_relations.with_log(self.undo_log)
}

#[inline]
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
self.storage.sub_relations.with_log(self.undo_log)
}

/// Returns a range of the type variables created during the snapshot.
pub(crate) fn vars_since_snapshot(
&mut self,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
pub use rustc_type_ir as ir;
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
pub use rustc_type_ir::CanonicalVarKind;
use smallvec::SmallVec;

use crate::mir::ConstraintCategory;
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use rustc_type_ir::{ConstKind, TypeFolder, VisitorResult, try_visit};

use super::print::PrettyPrinter;
use super::{GenericArg, GenericArgKind, Pattern, Region};
use crate::infer::canonical::CanonicalVarInfos;
use crate::mir::PlaceElem;
use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths};
use crate::ty::{
Expand Down Expand Up @@ -779,5 +778,4 @@ list_fold! {
ty::Clauses<'tcx> : mk_clauses,
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
CanonicalVarInfos<'tcx> : mk_canonical_var_infos,
}
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/typeck_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,8 @@ pub type CanonicalUserTypeAnnotations<'tcx> =

#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
#[type_foldable(identity)]
#[type_visitable(ignore)]
pub user_ty: Box<CanonicalUserType<'tcx>>,
pub span: Span,
pub inferred_ty: Ty<'tcx>,
Expand Down
Loading
Loading