Skip to content

Commit 24ee32c

Browse files
committed
borrowck: more eagerly prepopulate opaques
1 parent 5f044f3 commit 24ee32c

File tree

10 files changed

+78
-116
lines changed

10 files changed

+78
-116
lines changed

compiler/rustc_borrowck/src/lib.rs

+28
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ fn do_mir_borrowck<'tcx>(
182182
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
183183
let body = &body_owned; // no further changes
184184

185+
// FIXME(-Znext-solver): A bit dubious that we're only registering
186+
// predefined opaques in the typeck root.
187+
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
188+
infcx.register_predefined_opaques_for_next_solver(def);
189+
}
190+
185191
let location_table = LocationTable::new(body);
186192

187193
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
@@ -488,6 +494,28 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
488494

489495
next_region
490496
}
497+
498+
/// With the new solver we prepopulate the opaque type storage during
499+
/// MIR borrowck with the hidden types from HIR typeck. This is necessary
500+
/// to avoid ambiguities as earlier goals can rely on the hidden type
501+
/// of an opaque which is only constrained by a later goal.
502+
fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
503+
let tcx = self.tcx;
504+
// OK to use the identity arguments for each opaque type key, since
505+
// we remap opaques from HIR typeck back to their definition params.
506+
for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
507+
// HIR typeck did not infer the regions of the opaque, so we instantiate
508+
// them with fresh inference variables.
509+
let (key, hidden_ty) = tcx.fold_regions(data, |_, _| {
510+
self.next_nll_region_var_in_universe(
511+
NllRegionVariableOrigin::Existential { from_forall: false },
512+
ty::UniverseIndex::ROOT,
513+
)
514+
});
515+
516+
self.inject_new_hidden_type_unchecked(key, hidden_ty);
517+
}
518+
}
491519
}
492520

493521
impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {

compiler/rustc_borrowck/src/type_check/mod.rs

+1-70
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use rustc_middle::mir::tcx::PlaceTy;
2424
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2525
use rustc_middle::mir::*;
2626
use rustc_middle::traits::query::NoSolution;
27-
use rustc_middle::traits::ObligationCause;
2827
use rustc_middle::ty::adjustment::PointerCoercion;
2928
use rustc_middle::ty::cast::CastTy;
3029
use rustc_middle::ty::visit::TypeVisitableExt;
@@ -1028,7 +1027,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10281027
implicit_region_bound: ty::Region<'tcx>,
10291028
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
10301029
) -> Self {
1031-
let mut checker = Self {
1030+
Self {
10321031
infcx,
10331032
last_span: body.span,
10341033
body,
@@ -1039,74 +1038,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10391038
implicit_region_bound,
10401039
borrowck_context,
10411040
reported_errors: Default::default(),
1042-
};
1043-
1044-
// FIXME(-Znext-solver): A bit dubious that we're only registering
1045-
// predefined opaques in the typeck root.
1046-
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
1047-
checker.register_predefined_opaques_for_next_solver();
1048-
}
1049-
1050-
checker
1051-
}
1052-
1053-
pub(super) fn register_predefined_opaques_for_next_solver(&mut self) {
1054-
// OK to use the identity arguments for each opaque type key, since
1055-
// we remap opaques from HIR typeck back to their definition params.
1056-
let opaques: Vec<_> = self
1057-
.infcx
1058-
.tcx
1059-
.typeck(self.body.source.def_id().expect_local())
1060-
.concrete_opaque_types
1061-
.iter()
1062-
.map(|(k, v)| (*k, *v))
1063-
.collect();
1064-
1065-
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
1066-
self.infcx.next_nll_region_var_in_universe(
1067-
NllRegionVariableOrigin::Existential { from_forall: false },
1068-
ty::UniverseIndex::ROOT,
1069-
)
1070-
});
1071-
1072-
let param_env = self.param_env;
1073-
let result = self.fully_perform_op(
1074-
Locations::All(self.body.span),
1075-
ConstraintCategory::OpaqueType,
1076-
CustomTypeOp::new(
1077-
|ocx| {
1078-
let mut obligations = Vec::new();
1079-
for (opaque_type_key, hidden_ty) in renumbered_opaques {
1080-
let cause = ObligationCause::dummy();
1081-
ocx.infcx.insert_hidden_type(
1082-
opaque_type_key,
1083-
&cause,
1084-
param_env,
1085-
hidden_ty.ty,
1086-
&mut obligations,
1087-
)?;
1088-
1089-
ocx.infcx.add_item_bounds_for_hidden_type(
1090-
opaque_type_key.def_id.to_def_id(),
1091-
opaque_type_key.args,
1092-
cause,
1093-
param_env,
1094-
hidden_ty.ty,
1095-
&mut obligations,
1096-
);
1097-
}
1098-
1099-
ocx.register_obligations(obligations);
1100-
Ok(())
1101-
},
1102-
"register pre-defined opaques",
1103-
),
1104-
);
1105-
1106-
if result.is_err() {
1107-
self.infcx
1108-
.dcx()
1109-
.span_bug(self.body.span, "failed re-defining predefined opaques in mir typeck");
11101041
}
11111042
}
11121043

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

+13
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,19 @@ impl<'tcx> InferCtxt<'tcx> {
485485
Ok(InferOk { value: (), obligations })
486486
}
487487

488+
/// Insert a hidden type into the opaque type storage, making sure
489+
/// it hasn't previously been defined. This does not emit any
490+
/// constraints and it's the responsibility of the caller to make
491+
/// sure that the item bounds of the opaque are checked.
492+
pub fn inject_new_hidden_type_unchecked(
493+
&self,
494+
opaque_type_key: OpaqueTypeKey<'tcx>,
495+
hidden_ty: OpaqueHiddenType<'tcx>,
496+
) {
497+
let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
498+
assert_eq!(prev, None);
499+
}
500+
488501
/// Insert a hidden type into the opaque type storage, equating it
489502
/// with any previous entries if necessary.
490503
///

tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// when there are multiple inputs. The `dyn Bar` should default to `+
33
// 'static`. This used to erroneously generate an error (cc #62517).
44
//
5+
//@ revisions: current next
6+
//@[next] compile-flags: -Znext-solver
7+
//@ ignore-compare-mode-next-solver (explicit revisions)
58
//@ check-pass
69

710
trait Foo {

tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
14
//@ check-pass
25

36
pub fn main() {}

tests/ui/impl-trait/issues/issue-105826.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
14
//@ check-pass
25

36
use std::io::Write;

tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.next.stderr

-14
This file was deleted.

tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs

-29
This file was deleted.

tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.current.stderr renamed to tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0308]: mismatched types
2-
--> $DIR/illegal-upcast-from-impl-opaque.rs:26:5
2+
--> $DIR/upcast-defining-opaque.rs:21:5
33
|
44
LL | type Foo = impl Sized;
55
| ---------- the found opaque type
66
LL |
7-
LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
8-
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
7+
LL | fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
8+
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
99
LL | x
1010
| ^ expected trait `Super`, found trait `Sub`
1111
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] check-pass
5+
6+
#![feature(trait_upcasting, type_alias_impl_trait)]
7+
8+
trait Super {
9+
type Assoc;
10+
}
11+
12+
trait Sub: Super {}
13+
14+
impl<T: ?Sized> Super for T {
15+
type Assoc = i32;
16+
}
17+
18+
type Foo = impl Sized;
19+
20+
fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
21+
x //[current]~ mismatched types
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)