Skip to content

Commit 9d23763

Browse files
Fix PostBorrowckAnalysis for old solver
1 parent 75530e9 commit 9d23763

File tree

8 files changed

+173
-188
lines changed

8 files changed

+173
-188
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+33-120
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,17 @@ use rustc_lint_defs::builtin::{
1717
use rustc_middle::hir::nested_filter;
1818
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
1919
use rustc_middle::middle::stability::EvalResult;
20-
use rustc_middle::ty::error::TypeErrorToStringExt;
2120
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
2221
use rustc_middle::ty::util::{Discr, IntTypeExt};
2322
use rustc_middle::ty::{
24-
AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
25-
TypeVisitable, TypeVisitableExt, fold_regions,
23+
AdtDef, GenericArgKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, fold_regions,
2624
};
2725
use rustc_session::lint::builtin::UNINHABITED_STATIC;
2826
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2927
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
3028
use rustc_trait_selection::traits;
3129
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
3230
use tracing::{debug, instrument};
33-
use ty::TypingMode;
3431
use {rustc_attr_parsing as attr, rustc_hir as hir};
3532

3633
use super::compare_impl_item::check_type_bounds;
@@ -254,14 +251,18 @@ fn check_opaque_meets_bounds<'tcx>(
254251
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }
255252
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
256253
};
254+
255+
let misc_cause = ObligationCause::misc(span, def_id);
256+
257+
// FIXME: We should reveal the TAITs that end up in where clauses here, otherwise we
258+
// will not be able to match param-env candidates in the old solver, since we don't
259+
// have eq-modulo-normalization. This is less of a problem than it seems, since this
260+
// only matters if we have TAITs in where clauses, which isn't achievable with RPIT
261+
// anyways.
257262
let param_env = tcx.param_env(defining_use_anchor);
258263

259-
// FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
260-
let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
261-
TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
262-
} else {
263-
TypingMode::analysis_in_body(tcx, defining_use_anchor)
264-
});
264+
let infcx =
265+
tcx.infer_ctxt().build(TypingMode::post_borrowck_analysis(tcx, defining_use_anchor));
265266
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
266267

267268
let args = match origin {
@@ -275,8 +276,6 @@ fn check_opaque_meets_bounds<'tcx>(
275276
}),
276277
};
277278

278-
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
279-
280279
// `ReErased` regions appear in the "parent_args" of closures/coroutines.
281280
// We're ignoring them here and replacing them with fresh region variables.
282281
// See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
@@ -289,19 +288,11 @@ fn check_opaque_meets_bounds<'tcx>(
289288
_ => re,
290289
});
291290

292-
// HACK: We eagerly instantiate some bounds to report better errors for them...
293-
// This isn't necessary for correctness, since we register these bounds when
294-
// equating the opaque below, but we should clean this up in the new solver.
291+
// NOTE: We elaborate the explicit item bounds for better spans.
295292
for (predicate, pred_span) in
296-
tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
293+
traits::elaborate(tcx, tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args))
297294
{
298-
let predicate = predicate.fold_with(&mut BottomUpFolder {
299-
tcx,
300-
ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
301-
lt_op: |lt| lt,
302-
ct_op: |ct| ct,
303-
});
304-
295+
let predicate = ocx.normalize(&misc_cause, param_env, predicate);
305296
ocx.register_obligation(Obligation::new(
306297
tcx,
307298
ObligationCause::new(
@@ -314,24 +305,24 @@ fn check_opaque_meets_bounds<'tcx>(
314305
));
315306
}
316307

317-
let misc_cause = ObligationCause::misc(span, def_id);
318-
// FIXME: We should just register the item bounds here, rather than equating.
319-
// FIXME(const_trait_impl): When we do that, please make sure to also register
320-
// the `~const` bounds.
321-
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
322-
Ok(()) => {}
323-
Err(ty_err) => {
324-
// Some types may be left "stranded" if they can't be reached
325-
// from a lowered rustc_middle bound but they're mentioned in the HIR.
326-
// This will happen, e.g., when a nested opaque is inside of a non-
327-
// existent associated type, like `impl Trait<Missing = impl Trait>`.
328-
// See <tests/ui/impl-trait/stranded-opaque.rs>.
329-
let ty_err = ty_err.to_string(tcx);
330-
let guar = tcx.dcx().span_delayed_bug(
331-
span,
332-
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
308+
// And check the `~const` bounds for an RPIT.
309+
if tcx.is_conditionally_const(def_id) {
310+
for (predicate, pred_span) in tcx.const_conditions(def_id).instantiate(tcx, args) {
311+
let predicate = ocx.normalize(
312+
&misc_cause,
313+
param_env,
314+
predicate.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
333315
);
334-
return Err(guar);
316+
ocx.register_obligation(Obligation::new(
317+
tcx,
318+
ObligationCause::new(
319+
span,
320+
def_id,
321+
ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
322+
),
323+
param_env,
324+
predicate,
325+
));
335326
}
336327
}
337328

@@ -353,27 +344,7 @@ fn check_opaque_meets_bounds<'tcx>(
353344
let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?;
354345
ocx.resolve_regions_and_report_errors(defining_use_anchor, param_env, wf_tys)?;
355346

356-
if infcx.next_trait_solver() {
357-
Ok(())
358-
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
359-
origin
360-
{
361-
// HACK: this should also fall through to the hidden type check below, but the original
362-
// implementation had a bug where equivalent lifetimes are not identical. This caused us
363-
// to reject existing stable code that is otherwise completely fine. The real fix is to
364-
// compare the hidden types via our type equivalence/relation infra instead of doing an
365-
// identity check.
366-
let _ = infcx.take_opaque_types();
367-
Ok(())
368-
} else {
369-
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
370-
for (mut key, mut ty) in infcx.take_opaque_types() {
371-
ty.ty = infcx.resolve_vars_if_possible(ty.ty);
372-
key = infcx.resolve_vars_if_possible(key);
373-
sanity_check_found_hidden_type(tcx, key, ty)?;
374-
}
375-
Ok(())
376-
}
347+
Ok(())
377348
}
378349

379350
fn best_definition_site_of_opaque<'tcx>(
@@ -461,50 +432,6 @@ fn best_definition_site_of_opaque<'tcx>(
461432
}
462433
}
463434

464-
fn sanity_check_found_hidden_type<'tcx>(
465-
tcx: TyCtxt<'tcx>,
466-
key: ty::OpaqueTypeKey<'tcx>,
467-
mut ty: ty::OpaqueHiddenType<'tcx>,
468-
) -> Result<(), ErrorGuaranteed> {
469-
if ty.ty.is_ty_var() {
470-
// Nothing was actually constrained.
471-
return Ok(());
472-
}
473-
if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
474-
if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
475-
// Nothing was actually constrained, this is an opaque usage that was
476-
// only discovered to be opaque after inference vars resolved.
477-
return Ok(());
478-
}
479-
}
480-
let strip_vars = |ty: Ty<'tcx>| {
481-
ty.fold_with(&mut BottomUpFolder {
482-
tcx,
483-
ty_op: |t| t,
484-
ct_op: |c| c,
485-
lt_op: |l| match l.kind() {
486-
RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
487-
_ => l,
488-
},
489-
})
490-
};
491-
// Closures frequently end up containing erased lifetimes in their final representation.
492-
// These correspond to lifetime variables that never got resolved, so we patch this up here.
493-
ty.ty = strip_vars(ty.ty);
494-
// Get the hidden type.
495-
let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
496-
let hidden_ty = strip_vars(hidden_ty);
497-
498-
// If the hidden types differ, emit a type mismatch diagnostic.
499-
if hidden_ty == ty.ty {
500-
Ok(())
501-
} else {
502-
let span = tcx.def_span(key.def_id);
503-
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
504-
Err(ty.build_mismatch_error(&other, tcx)?.emit())
505-
}
506-
}
507-
508435
/// Check that the opaque's precise captures list is valid (if present).
509436
/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
510437
/// are technically GATs.
@@ -1801,11 +1728,7 @@ pub(super) fn check_coroutine_obligations(
18011728

18021729
debug!(?typeck_results.coroutine_stalled_predicates);
18031730

1804-
let mode = if tcx.next_trait_solver_globally() {
1805-
TypingMode::post_borrowck_analysis(tcx, def_id)
1806-
} else {
1807-
TypingMode::analysis_in_body(tcx, def_id)
1808-
};
1731+
let mode = TypingMode::post_borrowck_analysis(tcx, def_id);
18091732

18101733
let infcx = tcx
18111734
.infer_ctxt()
@@ -1825,15 +1748,5 @@ pub(super) fn check_coroutine_obligations(
18251748
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
18261749
}
18271750

1828-
if !tcx.next_trait_solver_globally() {
1829-
// Check that any hidden types found when checking these stalled coroutine obligations
1830-
// are valid.
1831-
for (key, ty) in infcx.take_opaque_types() {
1832-
let hidden_type = infcx.resolve_vars_if_possible(ty);
1833-
let key = infcx.resolve_vars_if_possible(key);
1834-
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
1835-
}
1836-
}
1837-
18381751
Ok(())
18391752
}

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -711,14 +711,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
711711
// Already reported.
712712
Overflow(OverflowError::Error(guar)) => {
713713
self.set_tainted_by_errors(guar);
714-
return guar
714+
return guar;
715715
},
716716

717717
Overflow(_) => {
718718
bug!("overflow should be handled before the `report_selection_error` path");
719719
}
720720

721721
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
722+
if let Err(guar) = expected_ty.error_reported() {
723+
return guar;
724+
}
725+
722726
let mut diag = self.dcx().struct_span_err(
723727
span,
724728
format!("the constant `{ct}` is not of type `{expected_ty}`"),

compiler/rustc_trait_selection/src/traits/normalize.rs

+51-28
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
};
@@ -11,7 +11,7 @@ use rustc_middle::span_bug;
1111
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
1212
use rustc_middle::ty::{
1313
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
14-
TypingMode,
14+
TypingMode, fold_regions,
1515
};
1616
use tracing::{debug, instrument};
1717

@@ -127,11 +127,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
127127
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
128128
// so we can ignore those.
129129
match infcx.typing_mode() {
130-
// 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 => {}
130+
TypingMode::Coherence | TypingMode::Analysis { .. } => {
131+
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
132+
}
133+
TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => {}
135134
}
136135

137136
value.has_type_flags(flags)
@@ -169,6 +168,39 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
169168

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

174206
impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> {
@@ -223,29 +255,20 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
223255
ty::Opaque => {
224256
// Only normalize `impl Trait` outside of type inference, usually in codegen.
225257
match self.selcx.infcx.typing_mode() {
226-
// 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-
);
258+
TypingMode::Coherence | TypingMode::Analysis { .. } => ty.super_fold_with(self),
259+
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
260+
if data
261+
.def_id
262+
.as_local()
263+
.is_some_and(|def_id| defined_opaque_types.contains(&def_id))
264+
{
265+
self.normalize_opaque_ty(ty, data)
266+
} else {
267+
// Treat non-defining opaques as rigid
268+
ty.super_fold_with(self)
239269
}
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
248270
}
271+
TypingMode::PostAnalysis => self.normalize_opaque_ty(ty, data),
249272
}
250273
}
251274

0 commit comments

Comments
 (0)