@@ -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.
952
+ for ty in & fcx. unsolved_variables ( ) {
953
+ fallback_has_occurred |= fcx. fallback_if_possible ( ty, false /* opaque_fallback */ ) ;
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.
940
983
for ty in & fcx. unsolved_variables ( ) {
941
- fallback_has_occurred |= fcx. fallback_if_possible ( ty) ;
984
+ fallback_has_occurred |= fcx. fallback_if_possible ( ty, true /* opaque_fallback */ ) ;
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
@@ -2864,8 +2909,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2864
2909
) ;
2865
2910
2866
2911
let mut opaque_types = self . opaque_types . borrow_mut ( ) ;
2912
+ let mut opaque_types_vars = self . opaque_types_vars . borrow_mut ( ) ;
2867
2913
for ( ty, decl) in opaque_type_map {
2868
2914
let _ = opaque_types. insert ( ty, decl) ;
2915
+ let _ = opaque_types_vars. insert ( decl. concrete_ty , decl. opaque_type ) ;
2869
2916
}
2870
2917
2871
2918
value
@@ -3078,7 +3125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3078
3125
// Fallback becomes very dubious if we have encountered type-checking errors.
3079
3126
// In that case, fallback to Error.
3080
3127
// The return value indicates whether fallback has occurred.
3081
- fn fallback_if_possible ( & self , ty : Ty < ' tcx > ) -> bool {
3128
+ fn fallback_if_possible ( & self , ty : Ty < ' tcx > , opaque_fallback : bool ) -> bool {
3082
3129
use rustc:: ty:: error:: UnconstrainedNumeric :: Neither ;
3083
3130
use rustc:: ty:: error:: UnconstrainedNumeric :: { UnconstrainedInt , UnconstrainedFloat } ;
3084
3131
@@ -3088,7 +3135,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3088
3135
UnconstrainedInt => self . tcx . types . i32 ,
3089
3136
UnconstrainedFloat => self . tcx . types . f64 ,
3090
3137
Neither if self . type_var_diverges ( ty) => self . tcx . mk_diverging_default ( ) ,
3091
- Neither => return false ,
3138
+ Neither => {
3139
+ // This type variable was created from the instantiation of an opaque
3140
+ // type. The fact that we're attempting to perform fallback for it
3141
+ // means that the function neither constrained it to a concrete
3142
+ // type, nor to the opaque type itself.
3143
+ //
3144
+ // For example, in this code:
3145
+ //
3146
+ //```
3147
+ // type MyType = impl Copy;
3148
+ // fn defining_use() -> MyType { true }
3149
+ // fn other_use() -> MyType { defining_use() }
3150
+ // ```
3151
+ //
3152
+ // `defining_use` will constrain the instantiated inference
3153
+ // variable to `bool`, while `other_use` will constrain
3154
+ // the instantiated inference variable to `MyType`.
3155
+ //
3156
+ // When we process opaque types during writeback, we
3157
+ // will handle cases like `other_use`, and not count
3158
+ // them as defining usages
3159
+ //
3160
+ // However, we also need to handle cases like this:
3161
+ //
3162
+ // ```rust
3163
+ // pub type Foo = impl Copy;
3164
+ // fn produce() -> Option<Foo> {
3165
+ // None
3166
+ // }
3167
+ // ```
3168
+ //
3169
+ // In the above snippet, the inference varaible created by
3170
+ // instantiating `Option<Foo>` will be completely unconstrained.
3171
+ // We treat this as a non-defining use by making the inference
3172
+ // variable fall back to the opaque type itself.
3173
+ if opaque_fallback {
3174
+ if let Some ( opaque_ty) = self . opaque_types_vars . borrow ( ) . get ( ty) {
3175
+ debug ! ( "fallback_if_possible: falling back opaque type var {:?} to {:?}" ,
3176
+ ty, opaque_ty) ;
3177
+ * opaque_ty
3178
+ } else {
3179
+ return false ;
3180
+ }
3181
+ } else {
3182
+ return false ;
3183
+ }
3184
+ } ,
3092
3185
} ;
3093
3186
debug ! ( "fallback_if_possible: defaulting `{:?}` to `{:?}`" , ty, fallback) ;
3094
3187
self . demand_eqtype ( syntax_pos:: DUMMY_SP , ty, fallback) ;
0 commit comments