Skip to content

Commit b2b7c85

Browse files
committed
Auto merge of rust-lang#87287 - oli-obk:fixup_fixup_fixup_opaque_types, r=spastorino
Make mir borrowck's use of opaque types independent of the typeck query's result fixes rust-lang#87218 fixes rust-lang#86465 we used to use the typeck results only to generate an obligation for the mir borrowck type to be equal to the typeck result. When i removed the `fixup_opaque_types` function in rust-lang#87200, I exposed a bug that showed that mir borrowck can't doesn't get enough information from typeck in order to build the correct lifetime mapping from opaque type usage to the actual concrete type. We therefor now fully compute the information within mir borrowck (we already did that, but we only used it to verify the typeck result) and stop using the typeck information. We will likely be able to remove most opaque type information from the borrowck results in the future and just have all current callers use the mir borrowck result instead. r? `@spastorino`
2 parents 0271870 + d103852 commit b2b7c85

30 files changed

+206
-301
lines changed

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#![feature(new_uninit)]
2525
#![feature(once_cell)]
2626
#![feature(maybe_uninit_uninit_array)]
27+
#![feature(min_type_alias_impl_trait)]
2728
#![allow(rustc::default_hash_types)]
2829
#![deny(unaligned_references)]
2930

compiler/rustc_data_structures/src/vec_map.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Borrow;
22
use std::iter::FromIterator;
3-
use std::slice::{Iter, IterMut};
3+
use std::slice::Iter;
44
use std::vec::IntoIter;
55

66
use crate::stable_hasher::{HashStable, StableHasher};
@@ -67,9 +67,13 @@ where
6767
self.into_iter()
6868
}
6969

70-
pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
70+
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
7171
self.into_iter()
7272
}
73+
74+
pub fn retain(&mut self, f: impl Fn(&(K, V)) -> bool) {
75+
self.0.retain(f)
76+
}
7377
}
7478

7579
impl<K, V> Default for VecMap<K, V> {
@@ -108,12 +112,12 @@ impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
108112
}
109113

110114
impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
111-
type Item = &'a mut (K, V);
112-
type IntoIter = IterMut<'a, (K, V)>;
115+
type Item = (&'a K, &'a mut V);
116+
type IntoIter = impl Iterator<Item = Self::Item>;
113117

114118
#[inline]
115119
fn into_iter(self) -> Self::IntoIter {
116-
self.0.iter_mut()
120+
self.0.iter_mut().map(|(k, v)| (&*k, v))
117121
}
118122
}
119123

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+51-89
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_middle::mir::*;
2626
use rustc_middle::ty::adjustment::PointerCast;
2727
use rustc_middle::ty::cast::CastTy;
2828
use rustc_middle::ty::fold::TypeFoldable;
29-
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
29+
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
3030
use rustc_middle::ty::{
3131
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
3232
ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
@@ -60,7 +60,6 @@ use crate::borrow_check::{
6060
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
6161
},
6262
region_infer::{ClosureRegionRequirementsExt, TypeTest},
63-
renumber,
6463
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
6564
universal_regions::{DefiningTy, UniversalRegions},
6665
Upvar,
@@ -180,7 +179,54 @@ pub(crate) fn type_check<'mir, 'tcx>(
180179
liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
181180

182181
translate_outlives_facts(&mut cx);
183-
cx.opaque_type_values
182+
let mut opaque_type_values = cx.opaque_type_values;
183+
184+
for (_, revealed_ty) in &mut opaque_type_values {
185+
*revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty);
186+
if revealed_ty.has_infer_types_or_consts() {
187+
infcx.tcx.sess.delay_span_bug(
188+
body.span,
189+
&format!("could not resolve {:#?}", revealed_ty.kind()),
190+
);
191+
*revealed_ty = infcx.tcx.ty_error();
192+
}
193+
}
194+
195+
opaque_type_values.retain(|(opaque_type_key, resolved_ty)| {
196+
let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
197+
*def_id == opaque_type_key.def_id
198+
} else {
199+
false
200+
};
201+
202+
if concrete_is_opaque {
203+
// We're using an opaque `impl Trait` type without
204+
// 'revealing' it. For example, code like this:
205+
//
206+
// type Foo = impl Debug;
207+
// fn foo1() -> Foo { ... }
208+
// fn foo2() -> Foo { foo1() }
209+
//
210+
// In `foo2`, we're not revealing the type of `Foo` - we're
211+
// just treating it as the opaque type.
212+
//
213+
// When this occurs, we do *not* want to try to equate
214+
// the concrete type with the underlying defining type
215+
// of the opaque type - this will always fail, since
216+
// the defining type of an opaque type is always
217+
// some other type (e.g. not itself)
218+
// Essentially, none of the normal obligations apply here -
219+
// we're just passing around some unknown opaque type,
220+
// without actually looking at the underlying type it
221+
// gets 'revealed' into
222+
debug!(
223+
"eq_opaque_type_and_type: non-defining use of {:?}",
224+
opaque_type_key.def_id,
225+
);
226+
}
227+
!concrete_is_opaque
228+
});
229+
opaque_type_values
184230
},
185231
);
186232

@@ -1239,14 +1285,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12391285
return Ok(());
12401286
}
12411287

1242-
let infcx = self.infcx;
1243-
let tcx = infcx.tcx;
12441288
let param_env = self.param_env;
12451289
let body = self.body;
12461290
let mir_def_id = body.source.def_id().expect_local();
12471291

1248-
// the "concrete opaque types" maps
1249-
let concrete_opaque_types = &tcx.typeck(mir_def_id).concrete_opaque_types;
12501292
let mut opaque_type_values = VecMap::new();
12511293

12521294
debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
@@ -1296,88 +1338,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12961338
.eq(output_ty, revealed_ty)?,
12971339
);
12981340

1299-
// For each opaque type `Foo<T>` inferred by this value, we want to equate
1300-
// the inference variable `?T` with the revealed type that was computed
1301-
// earlier by type check.
13021341
for &(opaque_type_key, opaque_decl) in &opaque_type_map {
1303-
let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
1304-
let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
1305-
*def_id == opaque_type_key.def_id
1306-
} else {
1307-
false
1308-
};
1309-
1310-
// The revealed type computed by the earlier phase of type check.
1311-
// In our example, this would be `(U, u32)`. Note that this references
1312-
// the type parameter `U` from the definition of `Foo`.
1313-
let concrete_ty = match concrete_opaque_types
1314-
.get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
1315-
{
1316-
None => {
1317-
if !concrete_is_opaque {
1318-
tcx.sess.delay_span_bug(
1319-
body.span,
1320-
&format!(
1321-
"Non-defining use of {:?} with revealed type",
1322-
opaque_type_key.def_id,
1323-
),
1324-
);
1325-
}
1326-
continue;
1327-
}
1328-
Some(concrete_ty) => concrete_ty,
1329-
};
1330-
debug!("concrete_ty = {:?}", concrete_ty);
1331-
1332-
// Apply the substitution, in this case `[U -> T]`, so that the
1333-
// concrete type becomes `Foo<(T, u32)>`
1334-
let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
1335-
1336-
// "Renumber" this, meaning that we replace all the regions
1337-
// with fresh inference variables. Not relevant to our example.
1338-
let renumbered_opaque_defn_ty =
1339-
renumber::renumber_regions(infcx, subst_opaque_defn_ty);
1340-
1341-
debug!(
1342-
"eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
1343-
concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
1344-
);
1345-
1346-
if !concrete_is_opaque {
1347-
// Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
1348-
// in our example) with the renumbered version that we took from
1349-
// the type check results (`Foo<(T, u32)>`).
1350-
obligations.add(
1351-
infcx
1352-
.at(&ObligationCause::dummy(), param_env)
1353-
.eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
1354-
);
1355-
opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty);
1356-
} else {
1357-
// We're using an opaque `impl Trait` type without
1358-
// 'revealing' it. For example, code like this:
1359-
//
1360-
// type Foo = impl Debug;
1361-
// fn foo1() -> Foo { ... }
1362-
// fn foo2() -> Foo { foo1() }
1363-
//
1364-
// In `foo2`, we're not revealing the type of `Foo` - we're
1365-
// just treating it as the opaque type.
1366-
//
1367-
// When this occurs, we do *not* want to try to equate
1368-
// the concrete type with the underlying defining type
1369-
// of the opaque type - this will always fail, since
1370-
// the defining type of an opaque type is always
1371-
// some other type (e.g. not itself)
1372-
// Essentially, none of the normal obligations apply here -
1373-
// we're just passing around some unknown opaque type,
1374-
// without actually looking at the underlying type it
1375-
// gets 'revealed' into
1376-
debug!(
1377-
"eq_opaque_type_and_type: non-defining use of {:?}",
1378-
opaque_type_key.def_id,
1379-
);
1380-
}
1342+
opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty);
13811343
}
13821344

13831345
debug!("eq_opaque_type_and_type: equated");
@@ -1405,7 +1367,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14051367
locations,
14061368
ConstraintCategory::OpaqueType,
14071369
CustomTypeOp::new(
1408-
|_cx| {
1370+
|infcx| {
14091371
infcx.constrain_opaque_type(
14101372
opaque_type_key,
14111373
&opaque_decl,

compiler/rustc_trait_selection/src/opaque_types.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub struct OpaqueTypeDecl<'tcx> {
8383
}
8484

8585
/// Whether member constraints should be generated for all opaque types
86+
#[derive(Debug)]
8687
pub enum GenerateMemberConstraints {
8788
/// The default, used by typeck
8889
WhenRequired,
@@ -354,8 +355,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
354355
opaque_types: &OpaqueTypeMap<'tcx>,
355356
free_region_relations: &FRR,
356357
) {
357-
debug!("constrain_opaque_types()");
358-
359358
for &(opaque_type_key, opaque_defn) in opaque_types {
360359
self.constrain_opaque_type(
361360
opaque_type_key,
@@ -367,6 +366,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
367366
}
368367

369368
/// See `constrain_opaque_types` for documentation.
369+
#[instrument(level = "debug", skip(self, free_region_relations))]
370370
fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
371371
&self,
372372
opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -376,15 +376,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
376376
) {
377377
let def_id = opaque_type_key.def_id;
378378

379-
debug!("constrain_opaque_type()");
380-
debug!("constrain_opaque_type: def_id={:?}", def_id);
381-
debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
382-
383379
let tcx = self.tcx;
384380

385381
let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
386382

387-
debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
383+
debug!(?concrete_ty);
388384

389385
let first_own_region = match opaque_defn.origin {
390386
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
@@ -397,7 +393,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
397393
// type foo::<'p0..'pn>::Foo<'q0..'qm>
398394
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
399395
//
400-
// For these types we onlt iterate over `'l0..lm` below.
396+
// For these types we only iterate over `'l0..lm` below.
401397
tcx.generics_of(def_id).parent_count
402398
}
403399
// These opaque type inherit all lifetime parameters from their
@@ -410,10 +406,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
410406
// If there are required region bounds, we can use them.
411407
if opaque_defn.has_required_region_bounds {
412408
let bounds = tcx.explicit_item_bounds(def_id);
413-
debug!("constrain_opaque_type: predicates: {:#?}", bounds);
409+
debug!("{:#?}", bounds);
414410
let bounds: Vec<_> =
415411
bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
416-
debug!("constrain_opaque_type: bounds={:#?}", bounds);
412+
debug!("{:#?}", bounds);
417413
let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
418414

419415
let required_region_bounds =
@@ -452,8 +448,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
452448
};
453449

454450
// Compute the least upper bound of it with the other regions.
455-
debug!("constrain_opaque_types: least_region={:?}", least_region);
456-
debug!("constrain_opaque_types: subst_region={:?}", subst_region);
451+
debug!(?least_region);
452+
debug!(?subst_region);
457453
match least_region {
458454
None => least_region = Some(subst_region),
459455
Some(lr) => {
@@ -484,7 +480,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
484480
}
485481

486482
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
487-
debug!("constrain_opaque_types: least_region={:?}", least_region);
483+
debug!(?least_region);
488484

489485
if let GenerateMemberConstraints::IfNoStaticBound = mode {
490486
if least_region != tcx.lifetimes.re_static {

src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ impl Bar for AssocNoCopy {
2929
impl Thing for AssocNoCopy {
3030
type Out = Box<dyn Bar<Assoc: Copy>>;
3131
//~^ ERROR the trait bound `String: Copy` is not satisfied
32-
//~| ERROR the trait bound `String: Copy` is not satisfied
3332

3433
fn func() -> Self::Out {
3534
Box::new(AssocNoCopy)

src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
44
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
55
| ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
66

7-
error[E0277]: the trait bound `String: Copy` is not satisfied
8-
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
9-
|
10-
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
11-
| ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

159
For more information about this error, try `rustc --explain E0277`.

src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
error: lifetime may not live long enough
2-
--> $DIR/ret-impl-trait-one.rs:10:80
2+
--> $DIR/ret-impl-trait-one.rs:10:65
33
|
4-
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
5-
| ________________________________--__--__________________________________________^
6-
| | | |
7-
| | | lifetime `'b` defined here
8-
| | lifetime `'a` defined here
9-
LL | |
10-
LL | | (a, b)
11-
LL | | }
12-
| |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
4+
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
5+
| -- -- ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
6+
| | |
7+
| | lifetime `'b` defined here
8+
| lifetime `'a` defined here
139
|
1410
= help: consider adding the following bound: `'b: 'a`
1511

src/test/ui/impl-trait/auto-trait-leak.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ fn main() {
1212
fn cycle1() -> impl Clone {
1313
//~^ ERROR cycle detected
1414
send(cycle2().clone());
15-
//~^ ERROR cannot be sent between threads safely
1615

1716
Rc::new(Cell::new(5))
1817
}

0 commit comments

Comments
 (0)