@@ -13,6 +13,7 @@ use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisit
13
13
use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , Subst , SubstsRef } ;
14
14
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
15
15
use rustc_span:: Span ;
16
+ use smallvec:: { smallvec, SmallVec } ;
16
17
17
18
use std:: ops:: ControlFlow ;
18
19
@@ -37,7 +38,11 @@ pub struct OpaqueTypeDecl<'tcx> {
37
38
/// fn foo<'a, 'b, T>() -> Foo<'a, T>
38
39
///
39
40
/// then `substs` would be `['a, T]`.
40
- pub substs : SubstsRef < ' tcx > ,
41
+ ///
42
+ /// In case there are multiple conflicting substs an error has already
43
+ /// been reported, but we still store the additional substs here in order
44
+ /// to allow for better diagnostics later.
45
+ pub substs : SmallVec < [ SubstsRef < ' tcx > ; 1 ] > ,
41
46
42
47
/// The span of this particular definition of the opaque type. So
43
48
/// for example:
@@ -429,11 +434,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
429
434
// If there are required region bounds, we can use them.
430
435
if opaque_defn. has_required_region_bounds {
431
436
let bounds = tcx. explicit_item_bounds ( def_id) ;
432
- debug ! ( "constrain_opaque_type: predicates: {:#?}" , bounds ) ;
437
+ debug ! ( ?bounds , "predicates" ) ;
433
438
let bounds: Vec < _ > =
434
- bounds. iter ( ) . map ( |( bound, _) | bound. subst ( tcx, opaque_defn. substs ) ) . collect ( ) ;
435
- debug ! ( "constrain_opaque_type: bounds={:#?}" , bounds) ;
436
- let opaque_type = tcx. mk_opaque ( def_id, opaque_defn. substs ) ;
439
+ bounds. iter ( ) . map ( |( bound, _) | bound. subst ( tcx, opaque_defn. substs [ 0 ] ) ) . collect ( ) ;
440
+ debug ! ( ? bounds) ;
441
+ let opaque_type = tcx. mk_opaque ( def_id, opaque_defn. substs [ 0 ] ) ;
437
442
438
443
let required_region_bounds =
439
444
required_region_bounds ( tcx, opaque_type, bounds. into_iter ( ) ) ;
@@ -459,7 +464,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
459
464
// second.
460
465
let mut least_region = None ;
461
466
462
- for subst_arg in & opaque_defn. substs [ first_own_region..] {
467
+ for subst_arg in & opaque_defn. substs [ 0 ] [ first_own_region..] {
463
468
let subst_region = match subst_arg. unpack ( ) {
464
469
GenericArgKind :: Lifetime ( r) => r,
465
470
GenericArgKind :: Type ( _) | GenericArgKind :: Const ( _) => continue ,
@@ -532,7 +537,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
532
537
// type can be equal to any of the region parameters of the
533
538
// opaque type definition.
534
539
let choice_regions: Lrc < Vec < ty:: Region < ' tcx > > > = Lrc :: new (
535
- opaque_defn. substs [ first_own_region..]
540
+ opaque_defn. substs [ 0 ] [ first_own_region..]
536
541
. iter ( )
537
542
. filter_map ( |arg| match arg. unpack ( ) {
538
543
GenericArgKind :: Lifetime ( r) => Some ( r) ,
@@ -1095,18 +1100,40 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
1095
1100
let tcx = infcx. tcx ;
1096
1101
1097
1102
// Use the same type variable if the exact same opaque type appears more
1098
- // than once in the return type (e.g., if it's passed to a type alias).
1099
- if let Some ( opaque_defn) = self . opaque_types . get ( & def_id) {
1100
- debug ! ( "instantiate_opaque_types: returning concrete ty {:?}" , opaque_defn. concrete_ty) ;
1101
- return opaque_defn. concrete_ty ;
1103
+ // than once in a function (e.g., if it's passed to a type alias).
1104
+ if let Some ( opaque_defn) = self . opaque_types . get_mut ( & def_id) {
1105
+ debug ! ( ?opaque_defn, "found already known concrete type" ) ;
1106
+ if opaque_defn. substs . contains ( & substs) {
1107
+ // Already seen this concrete type
1108
+ return opaque_defn. concrete_ty ;
1109
+ } else {
1110
+ // Don't emit multiple errors for the same set of substs
1111
+ opaque_defn. substs . push ( substs) ;
1112
+ tcx. sess
1113
+ . struct_span_err (
1114
+ self . value_span ,
1115
+ & format ! (
1116
+ "defining use generics {:?} differ from previous defining use" ,
1117
+ substs
1118
+ ) ,
1119
+ )
1120
+ . span_note (
1121
+ opaque_defn. definition_span ,
1122
+ & format ! (
1123
+ "previous defining use with different generics {:?} found here" ,
1124
+ opaque_defn. substs[ 0 ]
1125
+ ) ,
1126
+ )
1127
+ . delay_as_bug ( ) ;
1128
+ }
1102
1129
}
1103
1130
let span = tcx. def_span ( def_id) ;
1104
1131
debug ! ( ?self . value_span, ?span) ;
1105
1132
let ty_var = infcx
1106
1133
. next_ty_var ( TypeVariableOrigin { kind : TypeVariableOriginKind :: TypeInference , span } ) ;
1107
1134
1108
1135
let item_bounds = tcx. explicit_item_bounds ( def_id) ;
1109
- debug ! ( "instantiate_opaque_types: bounds={:#?}" , item_bounds) ;
1136
+ debug ! ( ? item_bounds) ;
1110
1137
let bounds: Vec < _ > =
1111
1138
item_bounds. iter ( ) . map ( |( bound, _) | bound. subst ( tcx, substs) ) . collect ( ) ;
1112
1139
@@ -1115,16 +1142,16 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
1115
1142
infcx. partially_normalize_associated_types_in ( span, self . body_id , param_env, bounds) ;
1116
1143
self . obligations . extend ( obligations) ;
1117
1144
1118
- debug ! ( "instantiate_opaque_types: bounds={:?}" , bounds) ;
1145
+ debug ! ( ? bounds) ;
1119
1146
1120
1147
let required_region_bounds = required_region_bounds ( tcx, ty, bounds. iter ( ) . copied ( ) ) ;
1121
- debug ! ( "instantiate_opaque_types: required_region_bounds={:?}" , required_region_bounds) ;
1148
+ debug ! ( ? required_region_bounds) ;
1122
1149
1123
1150
// Make sure that we are in fact defining the *entire* type
1124
1151
// (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
1125
1152
// defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
1126
- debug ! ( "instantiate_opaque_types: param_env={:#?}" , self . param_env, ) ;
1127
- debug ! ( "instantiate_opaque_types: generics={:#?}" , tcx. generics_of( def_id) , ) ;
1153
+ debug ! ( ? self . param_env, ) ;
1154
+ debug ! ( generics= ? tcx. generics_of( def_id) , ) ;
1128
1155
1129
1156
// Ideally, we'd get the span where *this specific `ty` came
1130
1157
// from*, but right now we just use the span from the overall
@@ -1133,18 +1160,22 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
1133
1160
// Foo, impl Bar)`.
1134
1161
let definition_span = self . value_span ;
1135
1162
1136
- self . opaque_types . insert (
1137
- def_id,
1138
- OpaqueTypeDecl {
1139
- opaque_type : ty,
1140
- substs,
1141
- definition_span,
1142
- concrete_ty : ty_var,
1143
- has_required_region_bounds : !required_region_bounds. is_empty ( ) ,
1144
- origin,
1145
- } ,
1146
- ) ;
1147
- debug ! ( "instantiate_opaque_types: ty_var={:?}" , ty_var) ;
1163
+ // We only keep the first concrete type var, as we will already error
1164
+ // out if there are multiple due to the conflicting obligations
1165
+ if !self . opaque_types . contains_key ( & def_id) {
1166
+ self . opaque_types . insert (
1167
+ def_id,
1168
+ OpaqueTypeDecl {
1169
+ opaque_type : ty,
1170
+ substs : smallvec ! [ substs] ,
1171
+ definition_span,
1172
+ concrete_ty : ty_var,
1173
+ has_required_region_bounds : !required_region_bounds. is_empty ( ) ,
1174
+ origin,
1175
+ } ,
1176
+ ) ;
1177
+ }
1178
+ debug ! ( ?ty_var) ;
1148
1179
1149
1180
for predicate in & bounds {
1150
1181
if let ty:: PredicateKind :: Projection ( projection) = predicate. kind ( ) . skip_binder ( ) {
0 commit comments