@@ -147,7 +147,7 @@ use crate::TypeAndSubsts;
147
147
use crate :: lint;
148
148
use crate :: util:: captures:: Captures ;
149
149
use crate :: util:: common:: { ErrorReported , indenter} ;
150
- use crate :: util:: nodemap:: { DefIdMap , DefIdSet , FxHashSet , HirIdMap } ;
150
+ use crate :: util:: nodemap:: { DefIdMap , DefIdSet , FxHashMap , FxHashSet , HirIdMap } ;
151
151
152
152
pub use self :: Expectation :: * ;
153
153
use self :: autoderef:: Autoderef ;
@@ -231,6 +231,13 @@ pub struct Inherited<'a, 'tcx> {
231
231
// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
232
232
opaque_types : RefCell < DefIdMap < OpaqueTypeDecl < ' tcx > > > ,
233
233
234
+ /// A map from inference variables created from opaque
235
+ /// type instantiations (`ty::Infer`) to the actual opaque
236
+ /// type (`ty::Opaque`). Used during fallback to map unconstrained
237
+ /// opaque type inference variables to their corresponding
238
+ /// opaque type.
239
+ opaque_types_vars : RefCell < FxHashMap < Ty < ' tcx > , Ty < ' tcx > > > ,
240
+
234
241
/// Each type parameter has an implicit region bound that
235
242
/// indicates it must outlive at least the function body (the user
236
243
/// may specify stronger requirements). This field indicates the
@@ -696,6 +703,7 @@ impl Inherited<'a, 'tcx> {
696
703
deferred_cast_checks : RefCell :: new ( Vec :: new ( ) ) ,
697
704
deferred_generator_interiors : RefCell :: new ( Vec :: new ( ) ) ,
698
705
opaque_types : RefCell :: new ( Default :: default ( ) ) ,
706
+ opaque_types_vars : RefCell :: new ( Default :: default ( ) ) ,
699
707
implicit_region_bound,
700
708
body_id,
701
709
}
@@ -937,9 +945,46 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
937
945
// All type checking constraints were added, try to fallback unsolved variables.
938
946
fcx. select_obligations_where_possible ( false , |_| { } ) ;
939
947
let mut fallback_has_occurred = false ;
948
+
949
+ // We do fallback in two passes, to try to generate
950
+ // better error messages.
951
+ // The first time, we do *not* replace opaque types.
940
952
for ty in & fcx. unsolved_variables ( ) {
941
- fallback_has_occurred |= fcx. fallback_if_possible ( ty) ;
953
+ fallback_has_occurred |= fcx. fallback_if_possible ( ty, FallbackMode :: NoOpaque ) ;
954
+ }
955
+ // We now see if we can make progress. This might
956
+ // cause us to unify inference variables for opaque types,
957
+ // since we may have unified some other type variables
958
+ // during the first phase of fallback.
959
+ // This means that we only replace inference variables with their underlying
960
+ // opaque types as a last resort.
961
+ //
962
+ // In code like this:
963
+ //
964
+ // ```rust
965
+ // type MyType = impl Copy;
966
+ // fn produce() -> MyType { true }
967
+ // fn bad_produce() -> MyType { panic!() }
968
+ // ```
969
+ //
970
+ // we want to unify the opaque inference variable in `bad_produce`
971
+ // with the diverging fallback for `panic!` (e.g. `()` or `!`).
972
+ // This will produce a nice error message about conflicting concrete
973
+ // types for `MyType`.
974
+ //
975
+ // If we had tried to fallback the opaque inference variable to `MyType`,
976
+ // we will generate a confusing type-check error that does not explicitly
977
+ // refer to opaque types.
978
+ fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
979
+
980
+ // We now run fallback again, but this time we allow it to replace
981
+ // unconstrained opaque type variables, in addition to performing
982
+ // other kinds of fallback.
983
+ for ty in & fcx. unsolved_variables ( ) {
984
+ fallback_has_occurred |= fcx. fallback_if_possible ( ty, FallbackMode :: All ) ;
942
985
}
986
+
987
+ // See if we can make any more progress.
943
988
fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
944
989
945
990
// Even though coercion casts provide type hints, we check casts after fallback for
@@ -2499,6 +2544,16 @@ enum TupleArgumentsFlag {
2499
2544
TupleArguments ,
2500
2545
}
2501
2546
2547
+ /// Controls how we perform fallback for unconstrained
2548
+ /// type variables.
2549
+ enum FallbackMode {
2550
+ /// Do not fallback type variables to opaque types.
2551
+ NoOpaque ,
2552
+ /// Perform all possible kinds of fallback, including
2553
+ /// turning type variables to opaque types.
2554
+ All ,
2555
+ }
2556
+
2502
2557
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
2503
2558
pub fn new (
2504
2559
inh : & ' a Inherited < ' a , ' tcx > ,
@@ -2864,8 +2919,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2864
2919
) ;
2865
2920
2866
2921
let mut opaque_types = self . opaque_types . borrow_mut ( ) ;
2922
+ let mut opaque_types_vars = self . opaque_types_vars . borrow_mut ( ) ;
2867
2923
for ( ty, decl) in opaque_type_map {
2868
2924
let _ = opaque_types. insert ( ty, decl) ;
2925
+ let _ = opaque_types_vars. insert ( decl. concrete_ty , decl. opaque_type ) ;
2869
2926
}
2870
2927
2871
2928
value
@@ -3078,7 +3135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3078
3135
// Fallback becomes very dubious if we have encountered type-checking errors.
3079
3136
// In that case, fallback to Error.
3080
3137
// The return value indicates whether fallback has occurred.
3081
- fn fallback_if_possible ( & self , ty : Ty < ' tcx > ) -> bool {
3138
+ fn fallback_if_possible ( & self , ty : Ty < ' tcx > , mode : FallbackMode ) -> bool {
3082
3139
use rustc:: ty:: error:: UnconstrainedNumeric :: Neither ;
3083
3140
use rustc:: ty:: error:: UnconstrainedNumeric :: { UnconstrainedInt , UnconstrainedFloat } ;
3084
3141
@@ -3088,7 +3145,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3088
3145
UnconstrainedInt => self . tcx . types . i32 ,
3089
3146
UnconstrainedFloat => self . tcx . types . f64 ,
3090
3147
Neither if self . type_var_diverges ( ty) => self . tcx . mk_diverging_default ( ) ,
3091
- Neither => return false ,
3148
+ Neither => {
3149
+ // This type variable was created from the instantiation of an opaque
3150
+ // type. The fact that we're attempting to perform fallback for it
3151
+ // means that the function neither constrained it to a concrete
3152
+ // type, nor to the opaque type itself.
3153
+ //
3154
+ // For example, in this code:
3155
+ //
3156
+ //```
3157
+ // type MyType = impl Copy;
3158
+ // fn defining_use() -> MyType { true }
3159
+ // fn other_use() -> MyType { defining_use() }
3160
+ // ```
3161
+ //
3162
+ // `defining_use` will constrain the instantiated inference
3163
+ // variable to `bool`, while `other_use` will constrain
3164
+ // the instantiated inference variable to `MyType`.
3165
+ //
3166
+ // When we process opaque types during writeback, we
3167
+ // will handle cases like `other_use`, and not count
3168
+ // them as defining usages
3169
+ //
3170
+ // However, we also need to handle cases like this:
3171
+ //
3172
+ // ```rust
3173
+ // pub type Foo = impl Copy;
3174
+ // fn produce() -> Option<Foo> {
3175
+ // None
3176
+ // }
3177
+ // ```
3178
+ //
3179
+ // In the above snippet, the inference varaible created by
3180
+ // instantiating `Option<Foo>` will be completely unconstrained.
3181
+ // We treat this as a non-defining use by making the inference
3182
+ // variable fall back to the opaque type itself.
3183
+ if let FallbackMode :: All = mode {
3184
+ if let Some ( opaque_ty) = self . opaque_types_vars . borrow ( ) . get ( ty) {
3185
+ debug ! ( "fallback_if_possible: falling back opaque type var {:?} to {:?}" ,
3186
+ ty, opaque_ty) ;
3187
+ * opaque_ty
3188
+ } else {
3189
+ return false ;
3190
+ }
3191
+ } else {
3192
+ return false ;
3193
+ }
3194
+ } ,
3092
3195
} ;
3093
3196
debug ! ( "fallback_if_possible: defaulting `{:?}` to `{:?}`" , ty, fallback) ;
3094
3197
self . demand_eqtype ( syntax_pos:: DUMMY_SP , ty, fallback) ;
0 commit comments