diff options
| author | Jubilee <46493976+workingjubilee@users.noreply.github.com> | 2024-06-12 20:03:21 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-12 20:03:21 -0700 |
| commit | f6cc226f09e959b2862bd14098aa7997dcecbe23 (patch) | |
| tree | 2652795ebb5507a23556a9ce10b5afa008a86c0e /compiler/rustc_trait_selection/src/traits/select | |
| parent | 100588ff314806bf3c2e02516a8cde36bb87263e (diff) | |
| parent | 4b809b9438e891ce28dbf90059f1149a7a5f19a2 (diff) | |
Rollup merge of #126353 - compiler-errors:move-match, r=lcnr
Move `MatchAgainstFreshVars` to old solver Small change I noticed when trying to uplift the relations to the new trait solver.
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/select')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/_match.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 4 |
2 files changed, 123 insertions, 2 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs new file mode 100644 index 00000000000..50d8e96aaf9 --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs @@ -0,0 +1,121 @@ +use rustc_infer::infer::relate::{ + self, structurally_relate_tys, Relate, RelateResult, TypeRelation, +}; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; +use tracing::{debug, instrument}; + +/// A type "A" *matches* "B" if the fresh types in B could be +/// instantiated with values so as to make it equal to A. Matching is +/// intended to be used only on freshened types, and it basically +/// indicates if the non-freshened versions of A and B could have been +/// unified. +/// +/// It is only an approximation. If it yields false, unification would +/// definitely fail, but a true result doesn't mean unification would +/// succeed. This is because we don't track the "side-constraints" on +/// type variables, nor do we track if the same freshened type appears +/// more than once. To some extent these approximations could be +/// fixed, given effort. +/// +/// Like subtyping, matching is really a binary relation, so the only +/// important thing about the result is Ok/Err. Also, matching never +/// affects any type variables or unification state. +pub struct MatchAgainstFreshVars<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> MatchAgainstFreshVars<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> { + MatchAgainstFreshVars { tcx } + } +} + +impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> { + fn tag(&self) -> &'static str { + "MatchAgainstFreshVars" + } + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>( + &mut self, + _: ty::Variance, + _: ty::VarianceDiagInfo<TyCtxt<'tcx>>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + self.relate(a, b) + } + + #[instrument(skip(self), level = "debug")] + fn regions( + &mut self, + a: ty::Region<'tcx>, + _b: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + Ok(a) + } + + #[instrument(skip(self), level = "debug")] + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + if a == b { + return Ok(a); + } + + match (a.kind(), b.kind()) { + ( + _, + &ty::Infer(ty::FreshTy(_)) + | &ty::Infer(ty::FreshIntTy(_)) + | &ty::Infer(ty::FreshFloatTy(_)), + ) => Ok(a), + + (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { + Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + } + + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)), + + _ => structurally_relate_tys(self, a, b), + } + } + + fn consts( + &mut self, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + debug!("{}.consts({:?}, {:?})", self.tag(), a, b); + if a == b { + return Ok(a); + } + + match (a.kind(), b.kind()) { + (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => { + return Ok(a); + } + + (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { + return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))); + } + + _ => {} + } + + relate::structurally_relate_consts(self, a, b) + } + + fn binders<T>( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> + where + T: Relate<TyCtxt<'tcx>>, + { + Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) + } +} diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4487ba60faa..212ef2e4b2b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,7 +32,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_infer::infer::relate::MatchAgainstFreshVars; use rustc_infer::infer::relate::TypeRelation; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; @@ -60,6 +59,7 @@ use std::ops::ControlFlow; pub use rustc_middle::traits::select::*; use rustc_middle::ty::print::with_no_trimmed_paths; +mod _match; mod candidate_assembly; mod confirmation; @@ -2719,7 +2719,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { previous: ty::PolyTraitPredicate<'tcx>, current: ty::PolyTraitPredicate<'tcx>, ) -> bool { - let mut matcher = MatchAgainstFreshVars::new(self.tcx()); + let mut matcher = _match::MatchAgainstFreshVars::new(self.tcx()); matcher.relate(previous, current).is_ok() } |
