Skip to content

Commit e7cc3bd

Browse files
committed
Auto merge of #92007 - oli-obk:lazy_tait2, r=nikomatsakis
Lazy type-alias-impl-trait Previously opaque types were processed by 1. replacing all mentions of them with inference variables 2. memorizing these inference variables in a side-table 3. at the end of typeck, resolve the inference variables in the side table and use the resolved type as the hidden type of the opaque type This worked okayish for `impl Trait` in return position, but required lots of roundabout type inference hacks and processing. This PR instead stops this process of replacing opaque types with inference variables, and just keeps the opaque types around. Whenever an opaque type `O` is compared with another type `T`, we make the comparison succeed and record `T` as the hidden type. If `O` is compared to `U` while there is a recorded hidden type for it, we grab the recorded type (`T`) and compare that against `U`. This makes implementing * rust-lang/rfcs#2515 much simpler (previous attempts on the inference based scheme were very prone to ICEs and general misbehaviour that was not explainable except by random implementation defined oddities). r? `@nikomatsakis` fixes #93411 fixes #88236
2 parents 734368a + 9822fff commit e7cc3bd

File tree

359 files changed

+3306
-2442
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

359 files changed

+3306
-2442
lines changed

compiler/rustc_borrowck/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@ fn mir_borrowck<'tcx>(
124124
) -> &'tcx BorrowCheckResult<'tcx> {
125125
let (input_body, promoted) = tcx.mir_promoted(def);
126126
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
127+
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
127128

128-
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
129+
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
129130
let input_body: &Body<'_> = &input_body.borrow();
130131
let promoted: &IndexVec<_, _> = &promoted.borrow();
131132
do_mir_borrowck(&infcx, input_body, promoted, false).0
@@ -140,7 +141,7 @@ fn mir_borrowck<'tcx>(
140141
/// If `return_body_with_facts` is true, then return the body with non-erased
141142
/// region ids on which the borrow checking was performed together with Polonius
142143
/// facts.
143-
#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
144+
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
144145
fn do_mir_borrowck<'a, 'tcx>(
145146
infcx: &InferCtxt<'a, 'tcx>,
146147
input_body: &Body<'tcx>,

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+38-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_data_structures::vec_map::VecMap;
33
use rustc_hir::OpaqueTyOrigin;
4-
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
54
use rustc_infer::infer::InferCtxt;
65
use rustc_middle::ty::subst::GenericArgKind;
76
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@@ -54,27 +53,44 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5453
pub(crate) fn infer_opaque_types(
5554
&self,
5655
infcx: &InferCtxt<'_, 'tcx>,
57-
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
56+
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (Ty<'tcx>, Span, OpaqueTyOrigin)>,
5857
span: Span,
5958
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
6059
opaque_ty_decls
6160
.into_iter()
62-
.filter_map(|(opaque_type_key, decl)| {
61+
.map(|(opaque_type_key, (concrete_type, decl_span, origin))| {
6362
let substs = opaque_type_key.substs;
64-
let concrete_type = decl.concrete_ty;
63+
// FIXME: why are the spans in decl_span often DUMMY_SP?
64+
let span = decl_span.substitute_dummy(span);
6565
debug!(?concrete_type, ?substs);
6666

6767
let mut subst_regions = vec![self.universal_regions.fr_static];
6868
let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
69-
let vid = self.universal_regions.to_region_vid(region);
70-
subst_regions.push(vid);
71-
self.definitions[vid].external_name.unwrap_or_else(|| {
72-
infcx
73-
.tcx
74-
.sess
75-
.delay_span_bug(span, "opaque type with non-universal region substs");
76-
infcx.tcx.lifetimes.re_static
77-
})
69+
if let ty::RePlaceholder(..) = region {
70+
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
71+
return region;
72+
}
73+
let vid = self.to_region_vid(region);
74+
trace!(?vid);
75+
let scc = self.constraint_sccs.scc(vid);
76+
trace!(?scc);
77+
match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
78+
self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
79+
}) {
80+
Some(region) => {
81+
let vid = self.universal_regions.to_region_vid(region);
82+
subst_regions.push(vid);
83+
region
84+
}
85+
None => {
86+
subst_regions.push(vid);
87+
infcx.tcx.sess.delay_span_bug(
88+
span,
89+
"opaque type with non-universal region substs",
90+
);
91+
infcx.tcx.lifetimes.re_static
92+
}
93+
}
7894
});
7995

8096
subst_regions.sort();
@@ -100,12 +116,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
100116
span,
101117
);
102118

103-
check_opaque_type_parameter_valid(
104-
infcx.tcx,
119+
(
105120
opaque_type_key,
106-
OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
121+
if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) {
122+
remapped_type
123+
} else {
124+
infcx.tcx.ty_error()
125+
},
107126
)
108-
.then_some((opaque_type_key, remapped_type))
109127
})
110128
.collect()
111129
}
@@ -149,9 +167,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
149167
fn check_opaque_type_parameter_valid(
150168
tcx: TyCtxt<'_>,
151169
opaque_type_key: OpaqueTypeKey<'_>,
152-
decl: OpaqueTypeDecl<'_>,
170+
origin: OpaqueTyOrigin,
171+
span: Span,
153172
) -> bool {
154-
match decl.origin {
173+
match origin {
155174
// No need to check return position impl trait (RPIT)
156175
// because for type and const parameters they are correct
157176
// by construction: we convert
@@ -177,7 +196,6 @@ fn check_opaque_type_parameter_valid(
177196
// Check these
178197
OpaqueTyOrigin::TyAlias => {}
179198
}
180-
let span = decl.definition_span;
181199
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
182200
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
183201
for (i, arg) in opaque_type_key.substs.iter().enumerate() {

compiler/rustc_borrowck/src/type_check/input_output.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
147147
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
148148
let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
149149
let output_span = body.local_decls[RETURN_PLACE].source_info.span;
150-
if let Err(terr) = self.eq_opaque_type_and_type(
151-
mir_output_ty,
150+
if let Err(terr) = self.eq_types(
152151
normalized_output_ty,
152+
mir_output_ty,
153153
Locations::All(output_span),
154154
ConstraintCategory::BoringNoLocation,
155155
) {
@@ -169,9 +169,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
169169
let user_provided_output_ty = user_provided_sig.output();
170170
let user_provided_output_ty =
171171
self.normalize(user_provided_output_ty, Locations::All(output_span));
172-
if let Err(err) = self.eq_opaque_type_and_type(
173-
mir_output_ty,
172+
if let Err(err) = self.eq_types(
174173
user_provided_output_ty,
174+
mir_output_ty,
175175
Locations::All(output_span),
176176
ConstraintCategory::BoringNoLocation,
177177
) {

0 commit comments

Comments
 (0)