@@ -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