]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/_match.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / _match.rs
CommitLineData
9fa01778 1use crate::ty::error::TypeError;
dfeec247
XL
2use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
3use crate::ty::{self, InferConst, Ty, TyCtxt};
c34b1796
AL
4
5/// A type "A" *matches* "B" if the fresh types in B could be
6/// substituted with values so as to make it equal to A. Matching is
7/// intended to be used only on freshened types, and it basically
8/// indicates if the non-freshened versions of A and B could have been
9/// unified.
10///
11/// It is only an approximation. If it yields false, unification would
12/// definitely fail, but a true result doesn't mean unification would
13/// succeed. This is because we don't track the "side-constraints" on
14/// type variables, nor do we track if the same freshened type appears
15/// more than once. To some extent these approximations could be
16/// fixed, given effort.
17///
18/// Like subtyping, matching is really a binary relation, so the only
19/// important thing about the result is Ok/Err. Also, matching never
20/// affects any type variables or unification state.
dc9dc135
XL
21pub struct Match<'tcx> {
22 tcx: TyCtxt<'tcx>,
416331ca 23 param_env: ty::ParamEnv<'tcx>,
c34b1796
AL
24}
25
a2a8927a 26impl<'tcx> Match<'tcx> {
416331ca
XL
27 pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> {
28 Match { tcx, param_env }
c34b1796
AL
29 }
30}
31
a2a8927a 32impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
dfeec247
XL
33 fn tag(&self) -> &'static str {
34 "Match"
35 }
36 fn tcx(&self) -> TyCtxt<'tcx> {
37 self.tcx
38 }
487cf647 39
dfeec247
XL
40 fn param_env(&self) -> ty::ParamEnv<'tcx> {
41 self.param_env
42 }
43 fn a_is_expected(&self) -> bool {
44 true
45 } // irrelevant
46
47 fn relate_with_variance<T: Relate<'tcx>>(
48 &mut self,
49 _: ty::Variance,
17df50a5 50 _: ty::VarianceDiagInfo<'tcx>,
f035d41b
XL
51 a: T,
52 b: T,
dfeec247 53 ) -> RelateResult<'tcx, T> {
c34b1796
AL
54 self.relate(a, b)
55 }
56
5e7ed085 57 #[instrument(skip(self), level = "debug")]
dfeec247
XL
58 fn regions(
59 &mut self,
60 a: ty::Region<'tcx>,
61 b: ty::Region<'tcx>,
62 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
c34b1796
AL
63 Ok(a)
64 }
65
5e7ed085 66 #[instrument(skip(self), level = "debug")]
c34b1796 67 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
dfeec247
XL
68 if a == b {
69 return Ok(a);
70 }
c34b1796 71
1b1a35ee 72 match (a.kind(), b.kind()) {
ba9703b0
XL
73 (
74 _,
75 &ty::Infer(ty::FreshTy(_))
76 | &ty::Infer(ty::FreshIntTy(_))
77 | &ty::Infer(ty::FreshFloatTy(_)),
78 ) => Ok(a),
c34b1796 79
dfeec247 80 (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
5099ac24 81 Err(TypeError::Sorts(relate::expected_found(self, a, b)))
c34b1796
AL
82 }
83
9ffffee4 84 (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
c34b1796 85
49aad941 86 _ => relate::structurally_relate_tys(self, a, b),
c34b1796
AL
87 }
88 }
89
48663c56
XL
90 fn consts(
91 &mut self,
5099ac24
FG
92 a: ty::Const<'tcx>,
93 b: ty::Const<'tcx>,
94 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
48663c56
XL
95 debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
96 if a == b {
97 return Ok(a);
98 }
99
923072b8 100 match (a.kind(), b.kind()) {
60c5eb7d 101 (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => {
48663c56
XL
102 return Ok(a);
103 }
104
60c5eb7d 105 (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
5099ac24 106 return Err(TypeError::ConstMismatch(relate::expected_found(self, a, b)));
48663c56
XL
107 }
108
109 _ => {}
110 }
111
49aad941 112 relate::structurally_relate_consts(self, a, b)
48663c56
XL
113 }
114
dfeec247
XL
115 fn binders<T>(
116 &mut self,
cdc7bbd5
XL
117 a: ty::Binder<'tcx, T>,
118 b: ty::Binder<'tcx, T>,
119 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
dfeec247
XL
120 where
121 T: Relate<'tcx>,
c34b1796 122 {
fc512014 123 Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
c34b1796
AL
124 }
125}