Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 319fe69

Browse files
committedJan 22, 2025
Fix PostBorrowckAnalysis for old solver
1 parent cd805f0 commit 319fe69

File tree

8 files changed

+184
-188
lines changed

8 files changed

+184
-188
lines changed
 

‎compiler/rustc_hir_analysis/src/check/check.rs

+34-121
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,17 @@ use rustc_middle::hir::nested_filter;
1616
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
1717
use rustc_middle::middle::stability::EvalResult;
1818
use rustc_middle::span_bug;
19-
use rustc_middle::ty::error::TypeErrorToStringExt;
20-
use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
19+
use rustc_middle::ty::fold::fold_regions;
2120
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
2221
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
2322
use rustc_middle::ty::{
24-
AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
23+
AdtDef, GenericArgKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
2524
};
2625
use rustc_session::lint::builtin::UNINHABITED_STATIC;
2726
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2827
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
2928
use rustc_trait_selection::traits;
3029
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
31-
use rustc_type_ir::fold::TypeFoldable;
3230
use tracing::{debug, instrument};
3331
use ty::TypingMode;
3432
use {rustc_attr_parsing as attr, rustc_hir as hir};
@@ -320,14 +318,18 @@ fn check_opaque_meets_bounds<'tcx>(
320318
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }
321319
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
322320
};
321+
322+
let misc_cause = ObligationCause::misc(span, def_id);
323+
324+
// FIXME: We should reveal the TAITs that end up in where clauses here, otherwise we
325+
// will not be able to match param-env candidates in the old solver, since we don't
326+
// have eq-modulo-normalization. This is less of a problem than it seems, since this
327+
// only matters if we have TAITs in where where clauses, which isn't achievable with
328+
// RPIT anyways.
323329
let param_env = tcx.param_env(defining_use_anchor);
324330

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-
});
331+
let infcx =
332+
tcx.infer_ctxt().build(TypingMode::post_borrowck_analysis(tcx, defining_use_anchor));
331333
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
332334

333335
let args = match origin {
@@ -341,8 +343,6 @@ fn check_opaque_meets_bounds<'tcx>(
341343
}),
342344
};
343345

344-
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
345-
346346
// `ReErased` regions appear in the "parent_args" of closures/coroutines.
347347
// We're ignoring them here and replacing them with fresh region variables.
348348
// See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
@@ -355,19 +355,11 @@ fn check_opaque_meets_bounds<'tcx>(
355355
_ => re,
356356
});
357357

358-
// HACK: We eagerly instantiate some bounds to report better errors for them...
359-
// This isn't necessary for correctness, since we register these bounds when
360-
// equating the opaque below, but we should clean this up in the new solver.
358+
// NOTE: We elaborate the explicit item bounds for better spans.
361359
for (predicate, pred_span) in
362-
tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
360+
traits::elaborate(tcx, tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args))
363361
{
364-
let predicate = predicate.fold_with(&mut BottomUpFolder {
365-
tcx,
366-
ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
367-
lt_op: |lt| lt,
368-
ct_op: |ct| ct,
369-
});
370-
362+
let predicate = ocx.normalize(&misc_cause, param_env, predicate);
371363
ocx.register_obligation(Obligation::new(
372364
tcx,
373365
ObligationCause::new(
@@ -379,25 +371,24 @@ fn check_opaque_meets_bounds<'tcx>(
379371
predicate,
380372
));
381373
}
382-
383-
let misc_cause = ObligationCause::misc(span, def_id);
384-
// FIXME: We should just register the item bounds here, rather than equating.
385-
// FIXME(const_trait_impl): When we do that, please make sure to also register
386-
// the `~const` bounds.
387-
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
388-
Ok(()) => {}
389-
Err(ty_err) => {
390-
// Some types may be left "stranded" if they can't be reached
391-
// from a lowered rustc_middle bound but they're mentioned in the HIR.
392-
// This will happen, e.g., when a nested opaque is inside of a non-
393-
// existent associated type, like `impl Trait<Missing = impl Trait>`.
394-
// See <tests/ui/impl-trait/stranded-opaque.rs>.
395-
let ty_err = ty_err.to_string(tcx);
396-
let guar = tcx.dcx().span_delayed_bug(
397-
span,
398-
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
374+
// And check the `~const` bounds for an RPIT.
375+
if tcx.is_conditionally_const(def_id) {
376+
for (predicate, pred_span) in tcx.const_conditions(def_id).instantiate(tcx, args) {
377+
let predicate = ocx.normalize(
378+
&misc_cause,
379+
param_env,
380+
predicate.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
399381
);
400-
return Err(guar);
382+
ocx.register_obligation(Obligation::new(
383+
tcx,
384+
ObligationCause::new(
385+
span,
386+
def_id,
387+
ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
388+
),
389+
param_env,
390+
predicate,
391+
));
401392
}
402393
}
403394

@@ -421,27 +412,7 @@ fn check_opaque_meets_bounds<'tcx>(
421412
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
422413
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
423414

424-
if infcx.next_trait_solver() {
425-
Ok(())
426-
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
427-
origin
428-
{
429-
// HACK: this should also fall through to the hidden type check below, but the original
430-
// implementation had a bug where equivalent lifetimes are not identical. This caused us
431-
// to reject existing stable code that is otherwise completely fine. The real fix is to
432-
// compare the hidden types via our type equivalence/relation infra instead of doing an
433-
// identity check.
434-
let _ = infcx.take_opaque_types();
435-
Ok(())
436-
} else {
437-
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
438-
for (mut key, mut ty) in infcx.take_opaque_types() {
439-
ty.ty = infcx.resolve_vars_if_possible(ty.ty);
440-
key = infcx.resolve_vars_if_possible(key);
441-
sanity_check_found_hidden_type(tcx, key, ty)?;
442-
}
443-
Ok(())
444-
}
415+
Ok(())
445416
}
446417

447418
fn best_definition_site_of_opaque<'tcx>(
@@ -535,50 +506,6 @@ fn best_definition_site_of_opaque<'tcx>(
535506
}
536507
}
537508

538-
fn sanity_check_found_hidden_type<'tcx>(
539-
tcx: TyCtxt<'tcx>,
540-
key: ty::OpaqueTypeKey<'tcx>,
541-
mut ty: ty::OpaqueHiddenType<'tcx>,
542-
) -> Result<(), ErrorGuaranteed> {
543-
if ty.ty.is_ty_var() {
544-
// Nothing was actually constrained.
545-
return Ok(());
546-
}
547-
if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
548-
if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
549-
// Nothing was actually constrained, this is an opaque usage that was
550-
// only discovered to be opaque after inference vars resolved.
551-
return Ok(());
552-
}
553-
}
554-
let strip_vars = |ty: Ty<'tcx>| {
555-
ty.fold_with(&mut BottomUpFolder {
556-
tcx,
557-
ty_op: |t| t,
558-
ct_op: |c| c,
559-
lt_op: |l| match l.kind() {
560-
RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
561-
_ => l,
562-
},
563-
})
564-
};
565-
// Closures frequently end up containing erased lifetimes in their final representation.
566-
// These correspond to lifetime variables that never got resolved, so we patch this up here.
567-
ty.ty = strip_vars(ty.ty);
568-
// Get the hidden type.
569-
let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
570-
let hidden_ty = strip_vars(hidden_ty);
571-
572-
// If the hidden types differ, emit a type mismatch diagnostic.
573-
if hidden_ty == ty.ty {
574-
Ok(())
575-
} else {
576-
let span = tcx.def_span(key.def_id);
577-
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
578-
Err(ty.build_mismatch_error(&other, tcx)?.emit())
579-
}
580-
}
581-
582509
/// Check that the opaque's precise captures list is valid (if present).
583510
/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
584511
/// are technically GATs.
@@ -1844,11 +1771,7 @@ pub(super) fn check_coroutine_obligations(
18441771

18451772
debug!(?typeck_results.coroutine_stalled_predicates);
18461773

1847-
let mode = if tcx.next_trait_solver_globally() {
1848-
TypingMode::post_borrowck_analysis(tcx, def_id)
1849-
} else {
1850-
TypingMode::analysis_in_body(tcx, def_id)
1851-
};
1774+
let mode = TypingMode::post_borrowck_analysis(tcx, def_id);
18521775

18531776
let infcx = tcx
18541777
.infer_ctxt()
@@ -1868,15 +1791,5 @@ pub(super) fn check_coroutine_obligations(
18681791
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
18691792
}
18701793

1871-
if !tcx.next_trait_solver_globally() {
1872-
// Check that any hidden types found when checking these stalled coroutine obligations
1873-
// are valid.
1874-
for (key, ty) in infcx.take_opaque_types() {
1875-
let hidden_type = infcx.resolve_vars_if_possible(ty);
1876-
let key = infcx.resolve_vars_if_possible(key);
1877-
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
1878-
}
1879-
}
1880-
18811794
Ok(())
18821795
}

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

-3
Original file line numberDiff line numberDiff line change
@@ -973,9 +973,6 @@ impl<'tcx> InferCtxt<'tcx> {
973973
TypingMode::Analysis { defining_opaque_types } => {
974974
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
975975
}
976-
// FIXME(#132279): This function is quite weird in post-analysis
977-
// and post-borrowck analysis mode. We may need to modify its uses
978-
// to support PostBorrowckAnalysis in the old solver as well.
979976
TypingMode::Coherence
980977
| TypingMode::PostBorrowckAnalysis { .. }
981978
| TypingMode::PostAnalysis => false,

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

+51-25
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use rustc_data_structures::stack::ensure_sufficient_stack;
44
use rustc_infer::infer::at::At;
5-
use rustc_infer::infer::{InferCtxt, InferOk};
5+
use rustc_infer::infer::{InferCtxt, InferOk, RegionVariableOrigin};
66
use rustc_infer::traits::{
77
FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine,
88
};
@@ -13,6 +13,7 @@ use rustc_middle::ty::{
1313
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
1414
TypingMode,
1515
};
16+
use rustc_type_ir::fold::fold_regions;
1617
use tracing::{debug, instrument};
1718

1819
use super::{
@@ -128,10 +129,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
128129
// so we can ignore those.
129130
match infcx.typing_mode() {
130131
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
131-
TypingMode::Coherence
132-
| TypingMode::Analysis { .. }
133-
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
134-
TypingMode::PostAnalysis => {}
132+
TypingMode::Coherence | TypingMode::Analysis { .. } => {
133+
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
134+
}
135+
TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => {}
135136
}
136137

137138
value.has_type_flags(flags)
@@ -169,6 +170,39 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
169170

170171
if !needs_normalization(self.selcx.infcx, &value) { value } else { value.fold_with(self) }
171172
}
173+
174+
fn normalize_opaque_ty(&mut self, ty: Ty<'tcx>, data: ty::AliasTy<'tcx>) -> Ty<'tcx> {
175+
let recursion_limit = self.cx().recursion_limit();
176+
if !recursion_limit.value_within_limit(self.depth) {
177+
self.selcx.infcx.err_ctxt().report_overflow_error(
178+
OverflowCause::DeeplyNormalize(data.into()),
179+
self.cause.span,
180+
true,
181+
|_| {},
182+
);
183+
}
184+
185+
let args = data.args.fold_with(self);
186+
let generic_ty = self.cx().type_of(data.def_id);
187+
let mut concrete_ty = generic_ty.instantiate(self.cx(), args);
188+
189+
if concrete_ty == ty {
190+
concrete_ty =
191+
Ty::new_error_with_message(self.cx(), self.cause.span, "recursive opaque type");
192+
}
193+
194+
let concrete_ty = fold_regions(self.cx(), concrete_ty, |re, _dbi| match re.kind() {
195+
ty::ReErased => self
196+
.selcx
197+
.infcx
198+
.next_region_var(RegionVariableOrigin::MiscVariable(self.cause.span)),
199+
_ => re,
200+
});
201+
self.depth += 1;
202+
let folded_ty = self.fold_ty(concrete_ty);
203+
self.depth -= 1;
204+
folded_ty
205+
}
172206
}
173207

174208
impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> {
@@ -224,28 +258,20 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
224258
// Only normalize `impl Trait` outside of type inference, usually in codegen.
225259
match self.selcx.infcx.typing_mode() {
226260
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
227-
TypingMode::Coherence
228-
| TypingMode::Analysis { .. }
229-
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
230-
TypingMode::PostAnalysis => {
231-
let recursion_limit = self.cx().recursion_limit();
232-
if !recursion_limit.value_within_limit(self.depth) {
233-
self.selcx.infcx.err_ctxt().report_overflow_error(
234-
OverflowCause::DeeplyNormalize(data.into()),
235-
self.cause.span,
236-
true,
237-
|_| {},
238-
);
261+
TypingMode::Coherence | TypingMode::Analysis { .. } => ty.super_fold_with(self),
262+
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
263+
if data
264+
.def_id
265+
.as_local()
266+
.is_some_and(|def_id| defined_opaque_types.contains(&def_id))
267+
{
268+
self.normalize_opaque_ty(ty, data)
269+
} else {
270+
// Treat non-defining opaques as rigid
271+
ty.super_fold_with(self)
239272
}
240-
241-
let args = data.args.fold_with(self);
242-
let generic_ty = self.cx().type_of(data.def_id);
243-
let concrete_ty = generic_ty.instantiate(self.cx(), args);
244-
self.depth += 1;
245-
let folded_ty = self.fold_ty(concrete_ty);
246-
self.depth -= 1;
247-
folded_ty
248273
}
274+
TypingMode::PostAnalysis => self.normalize_opaque_ty(ty, data),
249275
}
250276
}
251277

There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.