Skip to content

Commit 3bc801d

Browse files
committed
support revealing defined opaque post borrowck
1 parent 8285284 commit 3bc801d

File tree

24 files changed

+241
-63
lines changed

24 files changed

+241
-63
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
322322
};
323323
let param_env = tcx.param_env(defining_use_anchor);
324324

325-
// FIXME(#132279): This should eventually use the already defined hidden types.
326-
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
325+
// FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
326+
let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
327+
TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
328+
} else {
329+
TypingMode::analysis_in_body(tcx, defining_use_anchor)
330+
});
327331
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
328332

329333
let args = match origin {
@@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
417421
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
418422
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
419423

420-
if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin {
424+
if infcx.next_trait_solver() {
425+
Ok(())
426+
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
427+
origin
428+
{
421429
// HACK: this should also fall through to the hidden type check below, but the original
422430
// implementation had a bug where equivalent lifetimes are not identical. This caused us
423431
// to reject existing stable code that is otherwise completely fine. The real fix is to

compiler/rustc_hir_typeck/src/method/probe.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15741574
// Thus we need to prevent them from trying to match the `&_` autoref
15751575
// candidates that get created for `&self` trait methods.
15761576
ty::Alias(ty::Opaque, alias_ty)
1577-
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
1577+
if !self.next_trait_solver()
1578+
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
15781579
&& !xform_self_ty.is_ty_var() =>
15791580
{
15801581
return ProbeResult::NoMatch;

compiler/rustc_infer/src/infer/context.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
77
use rustc_middle::ty::{self, Ty, TyCtxt};
88
use rustc_span::{DUMMY_SP, ErrorGuaranteed};
99

10-
use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
10+
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
1111

1212
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
1313
type Interner = TyCtxt<'tcx>;
@@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
8787
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
8888
}
8989

90+
fn next_region_infer(&self) -> ty::Region<'tcx> {
91+
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
92+
}
93+
9094
fn next_ty_infer(&self) -> Ty<'tcx> {
9195
self.next_ty_var(DUMMY_SP)
9296
}

compiler/rustc_infer/src/infer/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {
990990

991991
#[inline(always)]
992992
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
993+
debug_assert!(!self.next_trait_solver());
993994
match self.typing_mode() {
994995
TypingMode::Analysis { defining_opaque_types } => {
995996
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
996997
}
997-
TypingMode::Coherence | TypingMode::PostAnalysis => false,
998+
// FIXME(#132279): This function is quite weird in post-analysis
999+
// and post-borrowck analysis mode. We may need to modify its uses
1000+
// to support PostBorrowckAnalysis in the old solver as well.
1001+
TypingMode::Coherence
1002+
| TypingMode::PostBorrowckAnalysis { .. }
1003+
| TypingMode::PostAnalysis => false,
9981004
}
9991005
}
10001006

@@ -1276,15 +1282,16 @@ impl<'tcx> InferCtxt<'tcx> {
12761282
/// using canonicalization or carrying this inference context around.
12771283
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
12781284
let typing_mode = match self.typing_mode() {
1279-
ty::TypingMode::Coherence => ty::TypingMode::Coherence,
12801285
// FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
12811286
// to handle them without proper canonicalization. This means we may cause cycle
12821287
// errors and fail to reveal opaques while inside of bodies. We should rename this
12831288
// function and require explicit comments on all use-sites in the future.
12841289
ty::TypingMode::Analysis { defining_opaque_types: _ } => {
12851290
TypingMode::non_body_analysis()
12861291
}
1287-
ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
1292+
mode @ (ty::TypingMode::Coherence
1293+
| ty::TypingMode::PostBorrowckAnalysis { .. }
1294+
| ty::TypingMode::PostAnalysis) => mode,
12881295
};
12891296
ty::TypingEnv { typing_mode, param_env }
12901297
}

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
9898
span: Span,
9999
param_env: ty::ParamEnv<'tcx>,
100100
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
101+
debug_assert!(!self.next_trait_solver());
101102
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
102103
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
103104
let def_id = def_id.expect_local();
@@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> {
546547
);
547548
}
548549
}
549-
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
550+
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
551+
bug!("insert hidden type in {mode:?}")
552+
}
550553
}
551554

552555
Ok(())

compiler/rustc_middle/src/ty/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
632632
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
633633
self.opaque_types_defined_by(defining_anchor)
634634
}
635+
636+
fn fold_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
637+
self,
638+
value: T,
639+
f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
640+
) -> T {
641+
self.fold_regions(value, f)
642+
}
635643
}
636644

637645
macro_rules! bidirectional_lang_item_map {

compiler/rustc_middle/src/ty/fold.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,11 @@ where
5555

5656
impl<'tcx> TyCtxt<'tcx> {
5757
/// Folds the escaping and free regions in `value` using `f`.
58-
pub fn fold_regions<T>(
58+
pub fn fold_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
5959
self,
6060
value: T,
6161
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
62-
) -> T
63-
where
64-
T: TypeFoldable<TyCtxt<'tcx>>,
65-
{
62+
) -> T {
6663
value.fold_with(&mut RegionFolder::new(self, &mut f))
6764
}
6865
}

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,9 @@ where
339339

340340
match self.typing_mode() {
341341
TypingMode::Coherence => {}
342-
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
342+
TypingMode::Analysis { .. }
343+
| TypingMode::PostBorrowckAnalysis { .. }
344+
| TypingMode::PostAnalysis => {
343345
self.discard_impls_shadowed_by_env(goal, &mut candidates);
344346
}
345347
}

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,12 @@ where
644644
}
645645
}
646646

647+
pub(super) fn next_region_var(&mut self) -> I::Region {
648+
let region = self.delegate.next_region_infer();
649+
self.inspect.add_var_value(region);
650+
region
651+
}
652+
647653
pub(super) fn next_ty_infer(&mut self) -> I::Ty {
648654
let ty = self.delegate.next_ty_infer();
649655
self.inspect.add_var_value(ty);

compiler/rustc_next_trait_solver/src/solve/mod.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod trait_goals;
2323

2424
use rustc_type_ir::inherent::*;
2525
pub use rustc_type_ir::solve::*;
26-
use rustc_type_ir::{self as ty, Interner};
26+
use rustc_type_ir::{self as ty, Interner, TypingMode};
2727
use tracing::instrument;
2828

2929
pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
@@ -321,6 +321,19 @@ where
321321
Ok(ct)
322322
}
323323
}
324+
325+
fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool {
326+
match self.typing_mode() {
327+
// Opaques are never rigid outside of analysis mode.
328+
TypingMode::Coherence | TypingMode::PostAnalysis => false,
329+
// During analysis, opaques are rigid unless they may be defined by
330+
// the current body.
331+
TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
332+
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
333+
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
334+
}
335+
}
336+
}
324337
}
325338

326339
fn response_no_constraints_raw<I: Interner>(

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+5-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod weak_types;
66
use rustc_type_ir::fast_reject::DeepRejectCtxt;
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9-
use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
9+
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
1010
use tracing::instrument;
1111

1212
use crate::delegate::SolverDelegate;
@@ -71,21 +71,10 @@ where
7171
Ok(())
7272
}
7373
ty::AliasTermKind::OpaqueTy => {
74-
match self.typing_mode() {
75-
// Opaques are never rigid outside of analysis mode.
76-
TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
77-
// During analysis, opaques are only rigid if we may not define it.
78-
TypingMode::Analysis { defining_opaque_types } => {
79-
if rigid_alias
80-
.def_id
81-
.as_local()
82-
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
83-
{
84-
Err(NoSolution)
85-
} else {
86-
Ok(())
87-
}
88-
}
74+
if self.opaque_type_is_rigid(rigid_alias.def_id) {
75+
Ok(())
76+
} else {
77+
Err(NoSolution)
8978
}
9079
}
9180
// FIXME(generic_const_exprs): we would need to support generic consts here

compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs

+20
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,26 @@ where
9595
);
9696
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
9797
}
98+
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
99+
let Some(def_id) = opaque_ty.def_id.as_local() else {
100+
return Err(NoSolution);
101+
};
102+
103+
if !defined_opaque_types.contains(&def_id) {
104+
return Err(NoSolution);
105+
}
106+
107+
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
108+
// FIXME: Actually use a proper binder here instead of relying on `ReErased`.
109+
//
110+
// This is also probably unsound or sth :shrug:
111+
let actual = cx.fold_regions(actual, |re, _dbi| match re.kind() {
112+
ty::ReErased => self.next_region_var(),
113+
_ => re,
114+
});
115+
self.eq(goal.param_env, expected, actual)?;
116+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
117+
}
98118
TypingMode::PostAnalysis => {
99119
// FIXME: Add an assertion that opaque type storage is empty.
100120
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ where
6969
// it's not a real impl.
7070
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
7171
TypingMode::Coherence => Certainty::AMBIGUOUS,
72-
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
72+
TypingMode::Analysis { .. }
73+
| TypingMode::PostBorrowckAnalysis { .. }
74+
| TypingMode::PostAnalysis => return Err(NoSolution),
7375
},
7476

7577
// Impl matches polarity
@@ -174,20 +176,7 @@ where
174176
// ideally we want to avoid, since we can make progress on this goal
175177
// via an alias bound or a locally-inferred hidden type instead.
176178
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
177-
match ecx.typing_mode() {
178-
TypingMode::Coherence | TypingMode::PostAnalysis => {
179-
unreachable!("rigid opaque outside of analysis: {goal:?}");
180-
}
181-
TypingMode::Analysis { defining_opaque_types } => {
182-
if opaque_ty
183-
.def_id
184-
.as_local()
185-
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
186-
{
187-
return Err(NoSolution);
188-
}
189-
}
190-
}
179+
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
191180
}
192181

193182
ecx.probe_and_evaluate_goal_for_constituent_tys(

compiler/rustc_trait_selection/src/solve/delegate.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
205205
// transmute checking and polymorphic MIR optimizations could
206206
// get a result which isn't correct for all monomorphizations.
207207
match self.typing_mode() {
208-
TypingMode::Coherence | TypingMode::Analysis { .. } => false,
208+
TypingMode::Coherence
209+
| TypingMode::Analysis { .. }
210+
| TypingMode::PostBorrowckAnalysis { .. } => false,
209211
TypingMode::PostAnalysis => {
210212
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
211213
!poly_trait_ref.still_further_specializable()

compiler/rustc_trait_selection/src/traits/normalize.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
118118
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
119119
// so we can ignore those.
120120
match infcx.typing_mode() {
121-
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
122-
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
123-
}
121+
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
122+
TypingMode::Coherence
123+
| TypingMode::Analysis { defining_opaque_types: _ }
124+
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
124125
TypingMode::PostAnalysis => {}
125126
}
126127

@@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
213214
ty::Opaque => {
214215
// Only normalize `impl Trait` outside of type inference, usually in codegen.
215216
match self.selcx.infcx.typing_mode() {
216-
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
217-
ty.super_fold_with(self)
218-
}
217+
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
218+
TypingMode::Coherence
219+
| TypingMode::Analysis { defining_opaque_types: _ }
220+
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
219221
TypingMode::PostAnalysis => {
220222
let recursion_limit = self.cx().recursion_limit();
221223
if !recursion_limit.value_within_limit(self.depth) {

compiler/rustc_trait_selection/src/traits/project.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
975975
// transmute checking and polymorphic MIR optimizations could
976976
// get a result which isn't correct for all monomorphizations.
977977
match selcx.infcx.typing_mode() {
978-
TypingMode::Coherence | TypingMode::Analysis { .. } => {
978+
TypingMode::Coherence
979+
| TypingMode::Analysis { .. }
980+
| TypingMode::PostBorrowckAnalysis { .. } => {
979981
debug!(
980982
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
981983
?obligation.predicate,

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
216216
ty::Opaque => {
217217
// Only normalize `impl Trait` outside of type inference, usually in codegen.
218218
match self.infcx.typing_mode() {
219-
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
220-
ty.try_super_fold_with(self)?
221-
}
219+
TypingMode::Coherence
220+
| TypingMode::Analysis { defining_opaque_types: _ }
221+
| TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
222222

223223
TypingMode::PostAnalysis => {
224224
let args = data.args.try_fold_with(self)?;

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14701470
let obligation = &stack.obligation;
14711471
match self.infcx.typing_mode() {
14721472
TypingMode::Coherence => {}
1473-
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
1473+
TypingMode::Analysis { .. }
1474+
| TypingMode::PostBorrowckAnalysis { .. }
1475+
| TypingMode::PostAnalysis => return Ok(()),
14741476
}
14751477

14761478
debug!("is_knowable()");
@@ -1517,6 +1519,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15171519
TypingMode::Analysis { defining_opaque_types } => {
15181520
defining_opaque_types.is_empty() || !pred.has_opaque_types()
15191521
}
1522+
// The hidden types of `defined_opaque_types` is not local to the current
1523+
// inference context, so we can freely move this to the global cache.
1524+
TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => true,
15201525
// The global cache is only used if there are no opaque types in
15211526
// the defining scope or we're outside of analysis.
15221527
//

compiler/rustc_ty_utils/src/instance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>(
149149
// get a result which isn't correct for all monomorphizations.
150150
match typing_env.typing_mode {
151151
ty::TypingMode::Coherence
152-
| ty::TypingMode::Analysis { defining_opaque_types: _ } => false,
152+
| ty::TypingMode::Analysis { .. }
153+
| ty::TypingMode::PostBorrowckAnalysis { .. } => false,
153154
ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
154155
}
155156
};

0 commit comments

Comments
 (0)