@@ -23,7 +23,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
23
23
use rustc_middle:: infer:: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind , ToType } ;
24
24
use rustc_middle:: mir:: interpret:: EvalToConstValueResult ;
25
25
use rustc_middle:: traits:: select;
26
- use rustc_middle:: ty:: error:: { ExpectedFound , TypeError , UnconstrainedNumeric } ;
26
+ use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
27
27
use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder } ;
28
28
use rustc_middle:: ty:: relate:: RelateResult ;
29
29
use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , SubstsRef } ;
@@ -46,7 +46,7 @@ use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, Veri
46
46
use self :: region_constraints:: {
47
47
RegionConstraintCollector , RegionConstraintStorage , RegionSnapshot ,
48
48
} ;
49
- use self :: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
49
+ use self :: type_variable:: { Diverging , TypeVariableOrigin , TypeVariableOriginKind } ;
50
50
51
51
pub mod at;
52
52
pub mod canonical;
@@ -679,10 +679,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
679
679
t. fold_with ( & mut self . freshener ( ) )
680
680
}
681
681
682
- pub fn type_var_diverges ( & ' a self , ty : Ty < ' _ > ) -> bool {
682
+ /// Returns whether `ty` is a diverging type variable or not.
683
+ /// (If `ty` is not a type variable at all, returns not diverging.)
684
+ ///
685
+ /// No attempt is made to resolve `ty`.
686
+ pub fn type_var_diverges ( & ' a self , ty : Ty < ' _ > ) -> Diverging {
683
687
match * ty. kind ( ) {
684
688
ty:: Infer ( ty:: TyVar ( vid) ) => self . inner . borrow_mut ( ) . type_variables ( ) . var_diverges ( vid) ,
685
- _ => false ,
689
+ _ => Diverging :: NotDiverging ,
690
+ }
691
+ }
692
+
693
+ /// Returns the origin of the type variable identified by `vid`, or `None`
694
+ /// if this is not a type variable.
695
+ ///
696
+ /// No attempt is made to resolve `ty`.
697
+ pub fn type_var_origin ( & ' a self , ty : Ty < ' tcx > ) -> Option < TypeVariableOrigin > {
698
+ match * ty. kind ( ) {
699
+ ty:: Infer ( ty:: TyVar ( vid) ) => {
700
+ Some ( * self . inner . borrow_mut ( ) . type_variables ( ) . var_origin ( vid) )
701
+ }
702
+ _ => None ,
686
703
}
687
704
}
688
705
@@ -695,28 +712,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
695
712
freshen:: TypeFreshener :: new ( self , true )
696
713
}
697
714
698
- pub fn type_is_unconstrained_numeric ( & ' a self , ty : Ty < ' _ > ) -> UnconstrainedNumeric {
699
- use rustc_middle:: ty:: error:: UnconstrainedNumeric :: Neither ;
700
- use rustc_middle:: ty:: error:: UnconstrainedNumeric :: { UnconstrainedFloat , UnconstrainedInt } ;
701
- match * ty. kind ( ) {
702
- ty:: Infer ( ty:: IntVar ( vid) ) => {
703
- if self . inner . borrow_mut ( ) . int_unification_table ( ) . probe_value ( vid) . is_some ( ) {
704
- Neither
705
- } else {
706
- UnconstrainedInt
707
- }
708
- }
709
- ty:: Infer ( ty:: FloatVar ( vid) ) => {
710
- if self . inner . borrow_mut ( ) . float_unification_table ( ) . probe_value ( vid) . is_some ( ) {
711
- Neither
712
- } else {
713
- UnconstrainedFloat
714
- }
715
- }
716
- _ => Neither ,
717
- }
718
- }
719
-
720
715
pub fn unsolved_variables ( & self ) -> Vec < Ty < ' tcx > > {
721
716
let mut inner = self . inner . borrow_mut ( ) ;
722
717
let mut vars: Vec < Ty < ' _ > > = inner
@@ -969,29 +964,62 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
969
964
) ;
970
965
}
971
966
967
+ /// Processes a `Coerce` predicate from the fulfillment context.
968
+ /// This is NOT the preferred way to handle coercion, which is to
969
+ /// invoke `FnCtxt::coerce` or a similar method (see `coercion.rs`).
970
+ ///
971
+ /// This method here is actually a fallback that winds up being
972
+ /// invoked when `FnCtxt::coerce` encounters unresolved type variables
973
+ /// and records a coercion predicate. Presently, this method is equivalent
974
+ /// to `subtype_predicate` -- that is, "coercing" `a` to `b` winds up
975
+ /// actually requiring `a <: b`. This is of course a valid coercion,
976
+ /// but it's not as flexible as `FnCtxt::coerce` would be.
977
+ ///
978
+ /// (We may refactor this in the future, but there are a number of
979
+ /// practical obstacles. Among other things, `FnCtxt::coerce` presently
980
+ /// records adjustments that are required on the HIR in order to perform
981
+ /// the coercion, and we don't currently have a way to manage that.)
982
+ pub fn coerce_predicate (
983
+ & self ,
984
+ cause : & ObligationCause < ' tcx > ,
985
+ param_env : ty:: ParamEnv < ' tcx > ,
986
+ predicate : ty:: PolyCoercePredicate < ' tcx > ,
987
+ ) -> Option < InferResult < ' tcx , ( ) > > {
988
+ let subtype_predicate = predicate. map_bound ( |p| ty:: SubtypePredicate {
989
+ a_is_expected : false , // when coercing from `a` to `b`, `b` is expected
990
+ a : p. a ,
991
+ b : p. b ,
992
+ } ) ;
993
+ self . subtype_predicate ( cause, param_env, subtype_predicate)
994
+ }
995
+
972
996
pub fn subtype_predicate (
973
997
& self ,
974
998
cause : & ObligationCause < ' tcx > ,
975
999
param_env : ty:: ParamEnv < ' tcx > ,
976
1000
predicate : ty:: PolySubtypePredicate < ' tcx > ,
977
1001
) -> Option < InferResult < ' tcx , ( ) > > {
978
- // Subtle: it's ok to skip the binder here and resolve because
979
- // `shallow_resolve` just ignores anything that is not a type
980
- // variable, and because type variable's can't (at present, at
1002
+ // Check for two unresolved inference variables, in which case we can
1003
+ // make no progress. This is partly a micro-optimization, but it's
1004
+ // also an opportunity to "sub-unify" the variables. This isn't
1005
+ // *necessary* to prevent cycles, because they would eventually be sub-unified
1006
+ // anyhow during generalization, but it helps with diagnostics (we can detect
1007
+ // earlier that they are sub-unified).
1008
+ //
1009
+ // Note that we can just skip the binders here because
1010
+ // type variables can't (at present, at
981
1011
// least) capture any of the things bound by this binder.
982
1012
//
983
- // NOTE(nmatsakis): really, there is no *particular* reason to do this
984
- // `shallow_resolve` here except as a micro-optimization.
985
- // Naturally I could not resist.
986
- let two_unbound_type_vars = {
987
- let a = self . shallow_resolve ( predicate. skip_binder ( ) . a ) ;
988
- let b = self . shallow_resolve ( predicate. skip_binder ( ) . b ) ;
989
- a. is_ty_var ( ) && b. is_ty_var ( )
990
- } ;
991
-
992
- if two_unbound_type_vars {
993
- // Two unbound type variables? Can't make progress.
994
- return None ;
1013
+ // Note that this sub here is not just for diagnostics - it has semantic
1014
+ // effects as well.
1015
+ let r_a = self . shallow_resolve ( predicate. skip_binder ( ) . a ) ;
1016
+ let r_b = self . shallow_resolve ( predicate. skip_binder ( ) . b ) ;
1017
+ match ( r_a. kind ( ) , r_b. kind ( ) ) {
1018
+ ( & ty:: Infer ( ty:: TyVar ( a_vid) ) , & ty:: Infer ( ty:: TyVar ( b_vid) ) ) => {
1019
+ self . inner . borrow_mut ( ) . type_variables ( ) . sub ( a_vid, b_vid) ;
1020
+ return None ;
1021
+ }
1022
+ _ => { }
995
1023
}
996
1024
997
1025
Some ( self . commit_if_ok ( |_snapshot| {
@@ -1020,25 +1048,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1020
1048
} )
1021
1049
}
1022
1050
1023
- pub fn next_ty_var_id ( & self , diverging : bool , origin : TypeVariableOrigin ) -> TyVid {
1051
+ pub fn next_ty_var_id ( & self , diverging : Diverging , origin : TypeVariableOrigin ) -> TyVid {
1024
1052
self . inner . borrow_mut ( ) . type_variables ( ) . new_var ( self . universe ( ) , diverging, origin)
1025
1053
}
1026
1054
1027
1055
pub fn next_ty_var ( & self , origin : TypeVariableOrigin ) -> Ty < ' tcx > {
1028
- self . tcx . mk_ty_var ( self . next_ty_var_id ( false , origin) )
1056
+ self . tcx . mk_ty_var ( self . next_ty_var_id ( Diverging :: NotDiverging , origin) )
1029
1057
}
1030
1058
1031
1059
pub fn next_ty_var_in_universe (
1032
1060
& self ,
1033
1061
origin : TypeVariableOrigin ,
1034
1062
universe : ty:: UniverseIndex ,
1035
1063
) -> Ty < ' tcx > {
1036
- let vid = self . inner . borrow_mut ( ) . type_variables ( ) . new_var ( universe, false , origin) ;
1064
+ let vid = self . inner . borrow_mut ( ) . type_variables ( ) . new_var (
1065
+ universe,
1066
+ Diverging :: NotDiverging ,
1067
+ origin,
1068
+ ) ;
1037
1069
self . tcx . mk_ty_var ( vid)
1038
1070
}
1039
1071
1040
1072
pub fn next_diverging_ty_var ( & self , origin : TypeVariableOrigin ) -> Ty < ' tcx > {
1041
- self . tcx . mk_ty_var ( self . next_ty_var_id ( true , origin) )
1073
+ self . tcx . mk_ty_var ( self . next_ty_var_id ( Diverging :: Diverges , origin) )
1042
1074
}
1043
1075
1044
1076
pub fn next_const_var (
@@ -1152,7 +1184,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1152
1184
// as the substitutions for the default, `(T, U)`.
1153
1185
let ty_var_id = self . inner . borrow_mut ( ) . type_variables ( ) . new_var (
1154
1186
self . universe ( ) ,
1155
- false ,
1187
+ Diverging :: NotDiverging ,
1156
1188
TypeVariableOrigin {
1157
1189
kind : TypeVariableOriginKind :: TypeParameterDefinition (
1158
1190
param. name ,
0 commit comments