1 // Copyright 2012 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
::*;
12 use super::{cres, CresCompare}
;
13 use super::equate
::Equate
;
15 use super::higher_ranked
::HigherRankedRelations
;
18 use super::{TypeTrace, Subtype}
;
19 use super::type_variable
::{SubtypeOf, SupertypeOf}
;
21 use middle
::ty
::{BuiltinBounds}
;
22 use middle
::ty
::{self, Ty}
;
23 use middle
::ty
::TyVar
;
24 use util
::ppaux
::{Repr}
;
26 use syntax
::ast
::{Onceness, MutImmutable, MutMutable, Unsafety}
;
29 /// "Greatest lower bound" (common subtype)
30 pub struct Sub
<'f
, 'tcx
: 'f
> {
31 fields
: CombineFields
<'f
, 'tcx
>
34 #[allow(non_snake_case)]
35 pub fn Sub
<'f
, 'tcx
>(cf
: CombineFields
<'f
, 'tcx
>) -> Sub
<'f
, 'tcx
> {
39 impl<'f
, 'tcx
> Combine
<'tcx
> for Sub
<'f
, 'tcx
> {
40 fn infcx
<'a
>(&'a
self) -> &'a InferCtxt
<'a
, 'tcx
> { self.fields.infcx }
41 fn tag(&self) -> String { "sub".to_string() }
42 fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
43 fn trace(&self) -> TypeTrace
<'tcx
> { self.fields.trace.clone() }
45 fn equate
<'a
>(&'a
self) -> Equate
<'a
, 'tcx
> { Equate(self.fields.clone()) }
46 fn sub
<'a
>(&'a
self) -> Sub
<'a
, 'tcx
> { Sub(self.fields.clone()) }
47 fn lub
<'a
>(&'a
self) -> Lub
<'a
, 'tcx
> { Lub(self.fields.clone()) }
48 fn glb
<'a
>(&'a
self) -> Glb
<'a
, 'tcx
> { Glb(self.fields.clone()) }
50 fn contratys(&self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> cres
<'tcx
, Ty
<'tcx
>> {
51 Sub(self.fields
.switch_expected()).tys(b
, a
)
54 fn contraregions(&self, a
: ty
::Region
, b
: ty
::Region
)
55 -> cres
<'tcx
, ty
::Region
> {
56 let opp
= CombineFields
{
57 a_is_expected
: !self.fields
.a_is_expected
,
60 Sub(opp
).regions(b
, a
)
63 fn regions(&self, a
: ty
::Region
, b
: ty
::Region
) -> cres
<'tcx
, ty
::Region
> {
64 debug
!("{}.regions({}, {})",
68 self.infcx().region_vars
.make_subregion(Subtype(self.trace()), a
, b
);
72 fn mts(&self, a
: &ty
::mt
<'tcx
>, b
: &ty
::mt
<'tcx
>) -> cres
<'tcx
, ty
::mt
<'tcx
>> {
73 debug
!("mts({} <: {})",
77 if a
.mutbl
!= b
.mutbl
{
78 return Err(ty
::terr_mutability
);
83 // If supertype is mut, subtype must match exactly
84 // (i.e., invariant if mut):
85 try
!(self.equate().tys(a
.ty
, b
.ty
));
88 // Otherwise we can be covariant:
89 try
!(self.tys(a
.ty
, b
.ty
));
93 Ok(*a
) // return is meaningless in sub, just return *a
96 fn unsafeties(&self, a
: Unsafety
, b
: Unsafety
) -> cres
<'tcx
, Unsafety
> {
97 self.lub().unsafeties(a
, b
).compare(b
, || {
98 ty
::terr_unsafety_mismatch(expected_found(self, a
, b
))
102 fn oncenesses(&self, a
: Onceness
, b
: Onceness
) -> cres
<'tcx
, Onceness
> {
103 self.lub().oncenesses(a
, b
).compare(b
, || {
104 ty
::terr_onceness_mismatch(expected_found(self, a
, b
))
108 fn builtin_bounds(&self, a
: BuiltinBounds
, b
: BuiltinBounds
)
109 -> cres
<'tcx
, BuiltinBounds
> {
110 // More bounds is a subtype of fewer bounds.
112 // e.g., fn:Copy() <: fn(), because the former is a function
113 // that only closes over copyable things, but the latter is
114 // any function at all.
115 if a
.is_superset(&b
) {
118 Err(ty
::terr_builtin_bounds(expected_found(self, a
, b
)))
122 fn tys(&self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> cres
<'tcx
, Ty
<'tcx
>> {
123 debug
!("{}.tys({}, {})", self.tag(),
124 a
.repr(self.tcx()), b
.repr(self.tcx()));
125 if a
== b { return Ok(a); }
127 let infcx
= self.fields
.infcx
;
128 let a
= infcx
.type_variables
.borrow().replace_if_possible(a
);
129 let b
= infcx
.type_variables
.borrow().replace_if_possible(b
);
130 match (&a
.sty
, &b
.sty
) {
131 (&ty
::ty_infer(TyVar(a_id
)), &ty
::ty_infer(TyVar(b_id
))) => {
134 .relate_vars(a_id
, SubtypeOf
, b_id
);
137 (&ty
::ty_infer(TyVar(a_id
)), _
) => {
140 .instantiate(b
, SupertypeOf
, a_id
));
143 (_
, &ty
::ty_infer(TyVar(b_id
))) => {
144 try
!(self.fields
.instantiate(a
, SubtypeOf
, b_id
));
148 (&ty
::ty_err
, _
) | (_
, &ty
::ty_err
) => {
149 Ok(self.tcx().types
.err
)
153 super_tys(self, a
, b
)
158 fn binders
<T
>(&self, a
: &ty
::Binder
<T
>, b
: &ty
::Binder
<T
>) -> cres
<'tcx
, ty
::Binder
<T
>>
159 where T
: Combineable
<'tcx
>
161 self.higher_ranked_sub(a
, b
)