Skip to content

Commit 38f50d1

Browse files
committed
Eagerly merge hidden types.
1 parent a745797 commit 38f50d1

17 files changed

+125
-79
lines changed

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
502502
let opaque = self.tcx.mk_opaque(key.def_id, substs);
503503
for &ty in tys {
504504
let ty = substitute_value(self.tcx, &result_subst, ty);
505-
obligations.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?);
505+
obligations
506+
.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?.obligations);
506507
}
507508
}
508509

compiler/rustc_infer/src/infer/opaque_types.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::infer::{InferCtxt, InferOk};
2-
use crate::traits::{self, PredicateObligation, PredicateObligations};
2+
use crate::traits::{self, PredicateObligation};
33
use hir::def_id::{DefId, LocalDefId};
44
use hir::OpaqueTyOrigin;
55
use rustc_data_structures::sync::Lrc;
@@ -20,6 +20,8 @@ mod table;
2020

2121
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
2222

23+
use super::InferResult;
24+
2325
/// Information about the opaque types whose values we
2426
/// are inferring in this function (these are the `impl Trait` that
2527
/// appear in the return type).
@@ -152,11 +154,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
152154
opaque: Ty<'tcx>,
153155
cause: ObligationCause<'tcx>,
154156
param_env: ty::ParamEnv<'tcx>,
155-
) -> Option<InferOk<'tcx, Ty<'tcx>>> {
156-
let mut obligations = vec![];
157-
let value = Instantiator { infcx: self, cause, param_env, obligations: &mut obligations }
158-
.fold_opaque_ty_new(opaque, |_, _| ty)?;
159-
Some(InferOk { value, obligations })
157+
) -> Option<InferResult<'tcx, ()>> {
158+
Instantiator { infcx: self, cause, param_env }.fold_opaque_ty_new(opaque, |_, _| ty)
160159
}
161160

162161
pub fn handle_opaque_type(
@@ -165,22 +164,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
165164
b: Ty<'tcx>,
166165
cause: &ObligationCause<'tcx>,
167166
param_env: ty::ParamEnv<'tcx>,
168-
) -> Result<PredicateObligations<'tcx>, TypeError<'tcx>> {
167+
) -> InferResult<'tcx, ()> {
169168
if a.references_error() || b.references_error() {
170-
return Ok(vec![]);
169+
return Ok(InferOk { value: (), obligations: vec![] });
171170
}
172171
if self.defining_use_anchor.is_some() {
173172
let process = |a: Ty<'tcx>, b: Ty<'tcx>| {
174173
if !matches!(a.kind(), ty::Opaque(..)) {
175174
return None;
176175
}
177176
self.instantiate_opaque_types(b, a, cause.clone(), param_env)
178-
.map(|res| res.obligations)
179177
};
180178
if let Some(res) = process(a, b) {
181-
Ok(res)
179+
res
182180
} else if let Some(res) = process(b, a) {
183-
Ok(res)
181+
res
184182
} else {
185183
// Rerun equality check, but this time error out due to
186184
// different types.
@@ -205,13 +203,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
205203
};
206204
let key = opaque_type.expect_opaque_type();
207205
let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span);
208-
self.inner.borrow_mut().opaque_types().register(
206+
let prev = self.inner.borrow_mut().opaque_types().register(
209207
key,
210208
opaque_type,
211209
OpaqueHiddenType { ty: hidden_ty, span: cause.span },
212210
origin,
213211
);
214-
Ok(vec![])
212+
match prev {
213+
Some(prev) => self.at(cause, param_env).eq(prev, hidden_ty),
214+
None => Ok(InferOk { value: (), obligations: vec![] }),
215+
}
215216
}
216217
}
217218

@@ -599,15 +600,14 @@ struct Instantiator<'a, 'tcx> {
599600
infcx: &'a InferCtxt<'a, 'tcx>,
600601
cause: ObligationCause<'tcx>,
601602
param_env: ty::ParamEnv<'tcx>,
602-
obligations: &'a mut PredicateObligations<'tcx>,
603603
}
604604

605605
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
606606
fn fold_opaque_ty_new(
607607
&mut self,
608608
ty: Ty<'tcx>,
609609
mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>,
610-
) -> Option<Ty<'tcx>> {
610+
) -> Option<InferResult<'tcx, ()>> {
611611
// Check that this is `impl Trait` type is
612612
// declared by `parent_def_id` -- i.e., one whose
613613
// value we are inferring. At present, this is
@@ -659,7 +659,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
659659
opaque_type_key: OpaqueTypeKey<'tcx>,
660660
origin: hir::OpaqueTyOrigin,
661661
mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>,
662-
) -> Ty<'tcx> {
662+
) -> InferResult<'tcx, ()> {
663663
let infcx = self.infcx;
664664
let tcx = infcx.tcx;
665665
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
@@ -673,12 +673,16 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
673673
// Foo, impl Bar)`.
674674
let span = self.cause.span;
675675

676-
self.infcx.inner.borrow_mut().opaque_types().register(
676+
let mut obligations = vec![];
677+
let prev = self.infcx.inner.borrow_mut().opaque_types().register(
677678
OpaqueTypeKey { def_id, substs },
678679
ty,
679680
OpaqueHiddenType { ty: ty_var, span },
680681
origin,
681682
);
683+
if let Some(prev) = prev {
684+
obligations = self.infcx.at(&self.cause, self.param_env).eq(prev, ty_var)?.obligations;
685+
}
682686

683687
debug!("generated new type inference var {:?}", ty_var.kind());
684688

@@ -698,7 +702,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
698702
projection_ty,
699703
self.cause.clone(),
700704
0,
701-
&mut self.obligations,
705+
&mut obligations,
702706
),
703707
// Replace all other mentions of the same opaque type with the hidden type,
704708
// as the bounds must hold on the hidden type after all.
@@ -714,19 +718,19 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
714718
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
715719
if projection.term.references_error() {
716720
// No point on adding these obligations since there's a type error involved.
717-
return tcx.ty_error();
721+
return Ok(InferOk { value: (), obligations: vec![] });
718722
}
719723
trace!("{:#?}", projection.term);
720724
}
721725
// Require that the predicate holds for the concrete type.
722726
debug!(?predicate);
723-
self.obligations.push(traits::Obligation::new(
727+
obligations.push(traits::Obligation::new(
724728
self.cause.clone(),
725729
self.param_env,
726730
predicate,
727731
));
728732
}
729-
ty_var
733+
Ok(InferOk { value: (), obligations })
730734
}
731735
}
732736

compiler/rustc_infer/src/infer/opaque_types/table.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ pub struct OpaqueTypeStorage<'tcx> {
1818

1919
impl<'tcx> OpaqueTypeStorage<'tcx> {
2020
#[instrument(level = "debug")]
21-
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: usize) {
22-
if idx == 0 {
21+
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
22+
if let Some(idx) = idx {
23+
self.opaque_types.get_mut(&key).unwrap().hidden_types[0] = idx;
24+
} else {
2325
match self.opaque_types.remove(&key) {
2426
None => bug!("reverted opaque type inference that was never registered: {:?}", key),
2527
Some(_) => {}
2628
}
27-
} else {
28-
self.opaque_types.get_mut(&key).unwrap().hidden_types.drain(idx..);
2929
}
3030
}
3131

@@ -75,14 +75,17 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
7575
opaque_type: Ty<'tcx>,
7676
ty: OpaqueHiddenType<'tcx>,
7777
origin: OpaqueTyOrigin,
78-
) {
78+
) -> Option<Ty<'tcx>> {
7979
if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
80-
decl.hidden_types.push(ty);
81-
self.undo_log.push(UndoLog::OpaqueTypes(key, decl.hidden_types.len()));
82-
return;
80+
assert_eq!(decl.hidden_types.len(), 1);
81+
let prev = decl.hidden_types[0];
82+
decl.hidden_types = vec![ty];
83+
self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
84+
return Some(prev.ty);
8385
}
8486
let decl = OpaqueTypeDecl { opaque_type, hidden_types: vec![ty], origin };
8587
self.storage.opaque_types.insert(key, decl);
86-
self.undo_log.push(UndoLog::OpaqueTypes(key, 0));
88+
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
89+
None
8790
}
8891
}

compiler/rustc_infer/src/infer/undo_log.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ use crate::{
1111
traits,
1212
};
1313

14+
use super::opaque_types::OpaqueHiddenType;
15+
1416
pub struct Snapshot<'tcx> {
1517
pub(crate) undo_len: usize,
1618
_marker: PhantomData<&'tcx ()>,
1719
}
1820

1921
/// Records the "undo" data for a single operation that affects some form of inference variable.
2022
pub(crate) enum UndoLog<'tcx> {
21-
OpaqueTypes(OpaqueTypeKey<'tcx>, usize),
23+
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
2224
TypeVariables(type_variable::UndoLog<'tcx>),
2325
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
2426
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
652652
&obligation.cause,
653653
obligation.param_env,
654654
) {
655-
Ok(value) => ProcessResult::Changed(mk_pending(value)),
655+
Ok(value) => ProcessResult::Changed(mk_pending(value.obligations)),
656656
Err(err) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
657657
ExpectedFound::new(true, a, b),
658658
err,

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
705705
&obligation.cause,
706706
obligation.param_env,
707707
) {
708-
Ok(obligations) => {
709-
self.evaluate_predicates_recursively(previous_stack, obligations)
708+
Ok(res) => {
709+
self.evaluate_predicates_recursively(previous_stack, res.obligations)
710710
}
711711
Err(_) => Ok(EvaluatedToErr),
712712
}

src/test/ui/impl-trait/equality.stderr

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ LL | #![feature(specialization)]
1111
error[E0308]: mismatched types
1212
--> $DIR/equality.rs:15:5
1313
|
14-
LL | return 1_i32;
15-
| ----- type expected due to this
16-
LL | }
14+
LL | fn two(x: bool) -> impl Foo {
15+
| -------- the expected opaque type
16+
...
1717
LL | 0_u32
1818
| ^^^^^ expected `i32`, found `u32`
19+
|
20+
= note: expected opaque type `impl Foo`
21+
found type `u32`
1922

2023
error[E0277]: cannot add `impl Foo` to `u32`
2124
--> $DIR/equality.rs:24:11

src/test/ui/impl-trait/issue-72911.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint>
1616

1717
fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
1818
//~^ ERROR: failed to resolve
19-
//~| ERROR `()` is not an iterator
2019
unimplemented!()
2120
}
2221

src/test/ui/impl-trait/issue-72911.stderr

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,7 @@ LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
1818
|
1919
= help: the trait `Iterator` is not implemented for `()`
2020

21-
error[E0277]: `()` is not an iterator
22-
--> $DIR/issue-72911.rs:17:20
23-
|
24-
LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
26-
|
27-
= help: the trait `Iterator` is not implemented for `()`
28-
29-
error: aborting due to 4 previous errors
21+
error: aborting due to 3 previous errors
3022

3123
Some errors have detailed explanations: E0277, E0433.
3224
For more information about an error, try `rustc --explain E0277`.

src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
2-
--> $DIR/ordinary-bounds-unrelated.rs:28:22
2+
--> $DIR/ordinary-bounds-unrelated.rs:28:33
33
|
44
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
55
| -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
66
...
77
LL | if condition() { a } else { b }
8-
| ^
8+
| ^
99
|
1010
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
1111
|

0 commit comments

Comments
 (0)