1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use super::combine
::{CombineFields, RelationDir}
;
14 use hir
::def_id
::DefId
;
16 use ty
::{self, Ty, TyCtxt}
;
18 use ty
::subst
::Substs
;
19 use ty
::relate
::{self, Relate, RelateResult, TypeRelation}
;
21 /// Ensures `a` is made equal to `b`. Returns `a` on success.
22 pub struct Equate
<'combine
, 'infcx
: 'combine
, 'gcx
: 'infcx
+'tcx
, 'tcx
: 'infcx
> {
23 fields
: &'combine
mut CombineFields
<'infcx
, 'gcx
, 'tcx
>,
27 impl<'combine
, 'infcx
, 'gcx
, 'tcx
> Equate
<'combine
, 'infcx
, 'gcx
, 'tcx
> {
28 pub fn new(fields
: &'combine
mut CombineFields
<'infcx
, 'gcx
, 'tcx
>, a_is_expected
: bool
)
29 -> Equate
<'combine
, 'infcx
, 'gcx
, 'tcx
>
31 Equate { fields: fields, a_is_expected: a_is_expected }
35 impl<'combine
, 'infcx
, 'gcx
, 'tcx
> TypeRelation
<'infcx
, 'gcx
, 'tcx
>
36 for Equate
<'combine
, 'infcx
, 'gcx
, 'tcx
>
38 fn tag(&self) -> &'
static str { "Equate" }
40 fn tcx(&self) -> TyCtxt
<'infcx
, 'gcx
, 'tcx
> { self.fields.tcx() }
42 fn a_is_expected(&self) -> bool { self.a_is_expected }
44 fn relate_item_substs(&mut self,
46 a_subst
: &'tcx Substs
<'tcx
>,
47 b_subst
: &'tcx Substs
<'tcx
>)
48 -> RelateResult
<'tcx
, &'tcx Substs
<'tcx
>>
50 // NB: Once we are equating types, we don't care about
51 // variance, so don't try to lookup the variance here. This
52 // also avoids some cycles (e.g. #41849) since looking up
53 // variance requires computing types which can require
54 // performing trait matching (which then performs equality
57 relate
::relate_substs(self, None
, a_subst
, b_subst
)
60 fn relate_with_variance
<T
: Relate
<'tcx
>>(&mut self,
64 -> RelateResult
<'tcx
, T
>
69 fn tys(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
70 debug
!("{}.tys({:?}, {:?})", self.tag(),
72 if a
== b { return Ok(a); }
74 let infcx
= self.fields
.infcx
;
75 let a
= infcx
.type_variables
.borrow_mut().replace_if_possible(a
);
76 let b
= infcx
.type_variables
.borrow_mut().replace_if_possible(b
);
77 match (&a
.sty
, &b
.sty
) {
78 (&ty
::TyInfer(TyVar(a_id
)), &ty
::TyInfer(TyVar(b_id
))) => {
79 infcx
.type_variables
.borrow_mut().equate(a_id
, b_id
);
83 (&ty
::TyInfer(TyVar(a_id
)), _
) => {
84 self.fields
.instantiate(b
, RelationDir
::EqTo
, a_id
, self.a_is_expected
)?
;
88 (_
, &ty
::TyInfer(TyVar(b_id
))) => {
89 self.fields
.instantiate(a
, RelationDir
::EqTo
, b_id
, self.a_is_expected
)?
;
94 self.fields
.infcx
.super_combine_tys(self, a
, b
)?
;
100 fn regions(&mut self, a
: ty
::Region
<'tcx
>, b
: ty
::Region
<'tcx
>)
101 -> RelateResult
<'tcx
, ty
::Region
<'tcx
>> {
102 debug
!("{}.regions({:?}, {:?})",
106 let origin
= Subtype(self.fields
.trace
.clone());
107 self.fields
.infcx
.region_vars
.make_eqregion(origin
, a
, b
);
111 fn binders
<T
>(&mut self, a
: &ty
::Binder
<T
>, b
: &ty
::Binder
<T
>)
112 -> RelateResult
<'tcx
, ty
::Binder
<T
>>
113 where T
: Relate
<'tcx
>
115 self.fields
.higher_ranked_sub(a
, b
, self.a_is_expected
)?
;
116 self.fields
.higher_ranked_sub(b
, a
, self.a_is_expected
)