1
Fork 0

Auto merge of #133619 - matthiaskrgr:rollup-7ywaheb, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #132782 (improvements on initial sysroot and libdir finding logics)
 - #133466 (Fix typos in pin.rs)
 - #133492 (bootstrap: allow skipping steps with start of path)
 - #133501 (support revealing defined opaque post borrowck)
 - #133530 (Use consistent wording in docs, use is zero instead of is 0)
 - #133538 (Better diagnostic for fn items in variadic functions)
 - #133590 (Rename `-Zparse-only`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-11-29 12:05:41 +00:00
commit 0c4f3a45b8
85 changed files with 535 additions and 317 deletions

View file

@ -34,6 +34,7 @@ use rustc_infer::infer::{
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::impls::{
@ -502,7 +503,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
// HIR typeck did not infer the regions of the opaque, so we instantiate
// them with fresh inference variables.
let (key, hidden_ty) = tcx.fold_regions(data, |_, _| {
let (key, hidden_ty) = fold_regions(tcx, data, |_, _| {
self.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
ty::UniverseIndex::ROOT,

View file

@ -18,6 +18,7 @@ use rustc_middle::mir::{
TerminatorKind,
};
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_span::Span;
@ -1100,7 +1101,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let ty = ty.fold_with(&mut OpaqueFolder { tcx });
let mut failed = false;
let ty = tcx.fold_regions(ty, |r, _depth| {
let ty = fold_regions(tcx, ty, |r, _depth| {
let r_vid = self.to_region_vid(r);
let r_scc = self.constraint_sccs.scc(r_vid);
@ -1273,7 +1274,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| {
fold_regions(tcx, value, |r, _db| {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representative(scc);

View file

@ -3,6 +3,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
use rustc_macros::extension;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
@ -117,7 +118,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
});
debug!(?opaque_type_key, ?arg_regions);
let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| {
let concrete_type = fold_regions(infcx.tcx, concrete_type, |region, _| {
arg_regions
.iter()
.find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid))
@ -204,7 +205,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(ty, |region, _| match *region {
fold_regions(tcx, ty, |region, _| match *region {
ty::ReVar(vid) => {
let scc = self.constraint_sccs.scc(vid);
@ -442,7 +443,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
let mut seen = vec![tcx.lifetimes.re_static];
let canonical_args = tcx.fold_regions(args, |r1, _| {
let canonical_args = fold_regions(tcx, args, |r1, _| {
if r1.is_error() {
r1
} else if let Some(&r2) = seen.iter().find(|&&r2| {

View file

@ -2,6 +2,7 @@ use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::visit::{MutVisitor, TyContext};
use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable};
use rustc_span::Symbol;
use tracing::{debug, instrument};
@ -68,7 +69,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
F: Fn() -> RegionCtxt,
{
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
self.infcx.tcx.fold_regions(value, |_region, _depth| {
fold_regions(self.infcx.tcx, value, |_region, _depth| {
self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
})
}

View file

@ -8,6 +8,7 @@ use rustc_middle::bug;
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_span::Span;
use rustc_trait_selection::traits::ScrubbedTraitError;
@ -216,7 +217,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
/// are dealt with during trait solving.
fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
if value.has_placeholders() {
self.tcx.fold_regions(value, |r, _| match *r {
fold_regions(self.tcx, value, |r, _| match *r {
ty::RePlaceholder(placeholder) => {
self.constraints.placeholder_region(self.infcx, placeholder)
}

View file

@ -26,6 +26,7 @@ use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
@ -213,7 +214,7 @@ pub(crate) fn type_check<'a, 'tcx>(
// Convert all regions to nll vars.
let (opaque_type_key, hidden_type) =
infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
fold_regions(infcx.tcx, (opaque_type_key, hidden_type), |region, _| {
match region.kind() {
ty::ReVar(_) => region,
ty::RePlaceholder(placeholder) => {
@ -2073,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
let unsize_to = tcx.fold_regions(ty, |r, _| {
let unsize_to = fold_regions(tcx, ty, |r, _| {
if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
});
self.prove_trait_ref(

View file

@ -26,7 +26,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_macros::extension;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::fold::{TypeFoldable, fold_regions};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
@ -824,7 +824,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.infcx.tcx.fold_regions(value, |region, _depth| {
fold_regions(self.infcx.tcx, value, |region, _depth| {
let name = region.get_name_or_anon();
debug!(?region, ?name);
@ -906,7 +906,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
}
}

View file

@ -418,7 +418,9 @@ fn run_compiler(
return early_exit();
}
if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
if sess.opts.unstable_opts.parse_crate_root_only
|| sess.opts.unstable_opts.show_span.is_some()
{
return early_exit();
}

View file

@ -17,7 +17,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
use rustc_middle::ty::{
@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
};
let param_env = tcx.param_env(defining_use_anchor);
// FIXME(#132279): This should eventually use the already defined hidden types.
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
// FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
} else {
TypingMode::analysis_in_body(tcx, defining_use_anchor)
});
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let args = match origin {
@ -346,7 +350,7 @@ fn check_opaque_meets_bounds<'tcx>(
// FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
// here rather than using ReErased.
let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() {
ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
_ => re,
});
@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin {
if infcx.next_trait_solver() {
Ok(())
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
origin
{
// HACK: this should also fall through to the hidden type check below, but the original
// implementation had a bug where equivalent lifetimes are not identical. This caused us
// to reject existing stable code that is otherwise completely fine. The real fix is to

View file

@ -34,6 +34,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug};
@ -1415,7 +1416,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
GenericParamKind::Lifetime { .. } => true,
_ => false,
});
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
ty::ReErased => {
if has_region_params {
ty::Region::new_error_with_message(

View file

@ -5,6 +5,7 @@ use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
@ -113,7 +114,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// so no need for ConstArg.
Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
let ty = tcx.fold_regions(ty, |r, _| {
let ty = fold_regions(tcx, ty, |r, _| {
if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
});
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) {

View file

@ -37,6 +37,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
@ -1569,7 +1570,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
);
let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here...
if value.has_escaping_bound_vars() {
return false;

View file

@ -5,6 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, TyCtxt, TypingMode};
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};
@ -75,7 +76,7 @@ fn diagnostic_hir_wf_check<'tcx>(
// This visitor can walk into binders, resulting in the `tcx_ty` to
// potentially reference escaping bound variables. We simply erase
// those here.
let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| {
let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| {
if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
});
let cause = traits::ObligationCause::new(

View file

@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer =
.label = used more than once
.previous_use_label = first use of `{$ident}`
hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function
.suggestion = use a function pointer instead
.help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
.note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
hir_typeck_fru_expr = this expression does not end in a comma...
hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression

View file

@ -797,3 +797,15 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> {
#[note(hir_typeck_teach_help)]
pub(crate) teach: bool,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)]
#[help]
#[note]
pub(crate) struct PassFnItemToVariadicFunction {
#[primary_span]
pub span: Span,
#[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")]
pub sugg_span: Span,
pub replace: String,
}

View file

@ -472,9 +472,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
}
ty::FnDef(..) => {
let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
let fn_item_spa = arg.span;
tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
span: fn_item_spa,
sugg_span: fn_item_spa.shrink_to_hi(),
replace: fn_ptr,
});
}
_ => {}
}

View file

@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// Thus we need to prevent them from trying to match the `&_` autoref
// candidates that get created for `&self` trait methods.
ty::Alias(ty::Opaque, alias_ty)
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
if !self.next_trait_solver()
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
&& !xform_self_ty.is_ty_var() =>
{
return ProbeResult::NoMatch;

View file

@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, fold_regions};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable};
use rustc_span::Span;
@ -827,7 +827,10 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
// no reason to keep regions around. They will be repopulated during MIR
// borrowck, and specifically region constraints will be populated during
// MIR typeck which is run on the new body.
value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
//
// We're not using `tcx.erase_regions` as that also anonymizes bound variables,
// regressing borrowck diagnostics.
value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased);
// Normalize consts in writeback, because GCE doesn't normalize eagerly.
if tcx.features().generic_const_exprs() {

View file

@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{DUMMY_SP, ErrorGuaranteed};
use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
type Interner = TyCtxt<'tcx>;
@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}
fn next_region_infer(&self) -> ty::Region<'tcx> {
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
}
fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(DUMMY_SP)
}

View file

@ -9,7 +9,7 @@ use rustc_data_structures::graph::implementation::{
use rustc_data_structures::intern::Interned;
use rustc_data_structures::unord::UnordSet;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::fold::{TypeFoldable, fold_regions};
use rustc_middle::ty::{
self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar,
Region, RegionVid, Ty, TyCtxt,
@ -974,7 +974,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r))
fold_regions(tcx, value, |r, _db| self.resolve_region(tcx, r))
}
fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {

View file

@ -33,7 +33,7 @@ use rustc_middle::traits::select;
pub use rustc_middle::ty::IntVarValue;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{
BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable,
BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions,
};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {
#[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
debug_assert!(!self.next_trait_solver());
match self.typing_mode() {
TypingMode::Analysis { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
}
TypingMode::Coherence | TypingMode::PostAnalysis => false,
// FIXME(#132279): This function is quite weird in post-analysis
// and post-borrowck analysis mode. We may need to modify its uses
// to support PostBorrowckAnalysis in the old solver as well.
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => false,
}
}
@ -1165,7 +1171,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
if value.has_infer_regions() {
let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
Ok(self.tcx.fold_regions(value, |re, _| {
Ok(fold_regions(self.tcx, value, |re, _| {
if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
}))
} else {
@ -1276,7 +1282,6 @@ impl<'tcx> InferCtxt<'tcx> {
/// using canonicalization or carrying this inference context around.
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
let typing_mode = match self.typing_mode() {
ty::TypingMode::Coherence => ty::TypingMode::Coherence,
// FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
// to handle them without proper canonicalization. This means we may cause cycle
// errors and fail to reveal opaques while inside of bodies. We should rename this
@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> {
ty::TypingMode::Analysis { defining_opaque_types: _ } => {
TypingMode::non_body_analysis()
}
ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis) => mode,
};
ty::TypingEnv { typing_mode, param_env }
}

View file

@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
debug_assert!(!self.next_trait_solver());
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local();
@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> {
);
}
}
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
bug!("insert hidden type in {mode:?}")
}
}
Ok(())

View file

@ -712,7 +712,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(no_analysis, true);
untracked!(no_leak_check, true);
untracked!(no_parallel_backend, true);
untracked!(parse_only, true);
untracked!(parse_crate_root_only, true);
// `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
untracked!(print_codegen_stats, true);

View file

@ -17,6 +17,7 @@ use smallvec::SmallVec;
use super::{ConstValue, SourceInfo};
use crate::mir;
use crate::ty::fold::fold_regions;
use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
rustc_index::newtype_index! {
@ -315,7 +316,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
/// All regions of `ty` must be of kind `ReVar` and must represent
/// universal regions *external* to the closure.
pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
let inner = fold_regions(tcx, ty, |r, depth| match r.kind() {
ty::ReVar(vid) => {
let br = ty::BoundRegion {
var: ty::BoundVar::new(vid.index()),
@ -334,7 +335,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
tcx: TyCtxt<'tcx>,
mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
) -> Ty<'tcx> {
tcx.fold_regions(self.inner, |r, depth| match r.kind() {
fold_regions(tcx, self.inner, |r, depth| match r.kind() {
ty::ReBound(debruijn, br) => {
debug_assert_eq!(debruijn, depth);
map(ty::RegionVid::new(br.var.index()))

View file

@ -2,9 +2,9 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
use rustc_type_ir::data_structures::DelayedMap;
pub use rustc_type_ir::fold::{
FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region, shift_vars,
FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, shift_region,
shift_vars,
};
use tracing::{debug, instrument};
use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
@ -50,85 +50,6 @@ where
}
}
///////////////////////////////////////////////////////////////////////////
// Region folder
impl<'tcx> TyCtxt<'tcx> {
/// Folds the escaping and free regions in `value` using `f`.
pub fn fold_regions<T>(
self,
value: T,
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
}
/// Folds over the substructure of a type, visiting its component
/// types and all regions that occur *free* within it.
///
/// That is, function pointer types and trait object can introduce
/// new bound regions which are not visited by this visitors as
/// they are not free; only regions that occur free will be
/// visited by `fld_r`.
pub struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
/// Stores the index of a binder *just outside* the stuff we have
/// visited. So this begins as INNERMOST; when we pass through a
/// binder, it is incremented (via `shift_in`).
current_index: ty::DebruijnIndex,
/// Callback invokes for each free region. The `DebruijnIndex`
/// points to the binder *just outside* the ones we have passed
/// through.
fold_region_fn:
&'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
}
impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
#[inline]
pub fn new(
tcx: TyCtxt<'tcx>,
fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> RegionFolder<'a, 'tcx> {
RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
}
}
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}
#[instrument(skip(self), level = "debug", ret)]
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region");
r
}
_ => {
debug!(?self.current_index, "folding free region");
(self.fold_region_fn)(r, self.current_index)
}
}
}
}
///////////////////////////////////////////////////////////////////////////
// Bound vars replacer

View file

@ -21,6 +21,7 @@ use tracing::{debug, instrument};
use super::TypingEnv;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::Providers;
use crate::ty::fold::fold_regions;
use crate::ty::layout::{FloatExt, IntegerExt};
use crate::ty::{
self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
@ -735,7 +736,7 @@ impl<'tcx> TyCtxt<'tcx> {
.filter(|decl| !decl.ignore_for_traits)
.map(move |decl| {
let mut vars = vec![];
let ty = self.fold_regions(decl.ty, |re, debruijn| {
let ty = fold_regions(self, decl.ty, |re, debruijn| {
assert_eq!(re, self.lifetimes.re_erased);
let var = ty::BoundVar::from_usize(vars.len());
vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));

View file

@ -339,7 +339,9 @@ where
match self.typing_mode() {
TypingMode::Coherence => {}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {
self.discard_impls_shadowed_by_env(goal, &mut candidates);
}
}

View file

@ -644,6 +644,12 @@ where
}
}
pub(super) fn next_region_var(&mut self) -> I::Region {
let region = self.delegate.next_region_infer();
self.inspect.add_var_value(region);
region
}
pub(super) fn next_ty_infer(&mut self) -> I::Ty {
let ty = self.delegate.next_ty_infer();
self.inspect.add_var_value(ty);

View file

@ -23,7 +23,7 @@ mod trait_goals;
use rustc_type_ir::inherent::*;
pub use rustc_type_ir::solve::*;
use rustc_type_ir::{self as ty, Interner};
use rustc_type_ir::{self as ty, Interner, TypingMode};
use tracing::instrument;
pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
@ -321,6 +321,19 @@ where
Ok(ct)
}
}
fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool {
match self.typing_mode() {
// Opaques are never rigid outside of analysis mode.
TypingMode::Coherence | TypingMode::PostAnalysis => false,
// During analysis, opaques are rigid unless they may be defined by
// the current body.
TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
}
}
}
}
fn response_no_constraints_raw<I: Interner>(

View file

@ -6,7 +6,7 @@ mod weak_types;
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
use tracing::instrument;
use crate::delegate::SolverDelegate;
@ -71,21 +71,10 @@ where
Ok(())
}
ty::AliasTermKind::OpaqueTy => {
match self.typing_mode() {
// Opaques are never rigid outside of analysis mode.
TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
// During analysis, opaques are only rigid if we may not define it.
TypingMode::Analysis { defining_opaque_types } => {
if rigid_alias
.def_id
.as_local()
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{
Err(NoSolution)
} else {
Ok(())
}
}
if self.opaque_type_is_rigid(rigid_alias.def_id) {
Ok(())
} else {
Err(NoSolution)
}
}
// FIXME(generic_const_exprs): we would need to support generic consts here

View file

@ -2,6 +2,7 @@
//! behaves differently depending on the current `TypingMode`.
use rustc_index::bit_set::GrowableBitSet;
use rustc_type_ir::fold::fold_regions;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner, TypingMode};
@ -95,6 +96,26 @@ where
);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
let Some(def_id) = opaque_ty.def_id.as_local() else {
return Err(NoSolution);
};
if !defined_opaque_types.contains(&def_id) {
return Err(NoSolution);
}
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
// FIXME: Actually use a proper binder here instead of relying on `ReErased`.
//
// This is also probably unsound or sth :shrug:
let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
ty::ReErased => self.next_region_var(),
_ => re,
});
self.eq(goal.param_env, expected, actual)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
TypingMode::PostAnalysis => {
// FIXME: Add an assertion that opaque type storage is empty.
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);

View file

@ -69,7 +69,9 @@ where
// it's not a real impl.
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
TypingMode::Coherence => Certainty::AMBIGUOUS,
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Err(NoSolution),
},
// Impl matches polarity
@ -174,20 +176,7 @@ where
// ideally we want to avoid, since we can make progress on this goal
// via an alias bound or a locally-inferred hidden type instead.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
match ecx.typing_mode() {
TypingMode::Coherence | TypingMode::PostAnalysis => {
unreachable!("rigid opaque outside of analysis: {goal:?}");
}
TypingMode::Analysis { defining_opaque_types } => {
if opaque_ty
.def_id
.as_local()
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{
return Err(NoSolution);
}
}
}
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
}
ecx.probe_and_evaluate_goal_for_constituent_tys(

View file

@ -1208,7 +1208,7 @@ impl Options {
/// Returns `true` if there will be an output file generated.
pub fn will_create_output_file(&self) -> bool {
!self.unstable_opts.parse_only && // The file is just being parsed
!self.unstable_opts.parse_crate_root_only && // The file is just being parsed
self.unstable_opts.ls.is_empty() // The file is just being queried
}
@ -1864,7 +1864,7 @@ fn parse_output_types(
matches: &getopts::Matches,
) -> OutputTypes {
let mut output_types = BTreeMap::new();
if !unstable_opts.parse_only {
if !unstable_opts.parse_crate_root_only {
for list in matches.opt_strs("emit") {
for output_type in list.split(',') {
let (shorthand, path) = split_out_file_name(output_type);

View file

@ -1937,8 +1937,9 @@ options! {
"support compiling tests with panic=abort (default: no)"),
panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
"panic strategy for panics in drops"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link (default: no)"),
parse_crate_root_only: bool = (false, parse_bool, [UNTRACKED],
"parse the crate root file only; do not parse other files, compile, assemble, or link \
(default: no)"),
patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
"nop padding at function entry"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
@ -2036,7 +2037,7 @@ written to standard error output)"),
shell_argfiles: bool = (false, parse_bool, [UNTRACKED],
"allow argument files to be specified with POSIX \"shell-style\" argument quoting"),
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
"show spans for compiler debugging (expr|pat|ty)"),
"show spans in the crate root file, for compiler debugging (expr|pat|ty)"),
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
to rust's source base directory. only meant for testing purposes"),

View file

@ -3,6 +3,7 @@
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use tracing::instrument;
@ -83,7 +84,7 @@ pub fn find_param_with_region<'tcx>(
// May return None; sometimes the tables are not yet populated.
let ty = fn_sig.inputs()[index];
let mut found_anon_region = false;
let new_param_ty = tcx.fold_regions(ty, |r, _| {
let new_param_ty = fold_regions(tcx, ty, |r, _| {
if r == anon_region {
found_anon_region = true;
replace_region

View file

@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
match self.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { .. } => false,
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => false,
TypingMode::PostAnalysis => {
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
!poly_trait_ref.still_further_specializable()

View file

@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
// so we can ignore those.
match infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
}
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
TypingMode::PostAnalysis => {}
}
@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
ty::Opaque => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.selcx.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
ty.super_fold_with(self)
}
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
TypingMode::PostAnalysis => {
let recursion_limit = self.cx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {

View file

@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
match selcx.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { .. } => {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {
debug!(
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
?obligation.predicate,

View file

@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
ty::Opaque => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
ty.try_super_fold_with(self)?
}
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
TypingMode::PostAnalysis => {
let args = data.args.try_fold_with(self)?;

View file

@ -25,6 +25,7 @@ use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds};
pub use rustc_middle::traits::select::*;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{
self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
@ -1470,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let obligation = &stack.obligation;
match self.infcx.typing_mode() {
TypingMode::Coherence => {}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Ok(()),
}
debug!("is_knowable()");
@ -1517,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
TypingMode::Analysis { defining_opaque_types } => {
defining_opaque_types.is_empty() || !pred.has_opaque_types()
}
// The hidden types of `defined_opaque_types` is not local to the current
// inference context, so we can freely move this to the global cache.
TypingMode::PostBorrowckAnalysis { .. } => true,
// The global cache is only used if there are no opaque types in
// the defining scope or we're outside of analysis.
//
@ -3209,7 +3215,7 @@ fn bind_coroutine_hidden_types_above<'tcx>(
// Only remap erased regions if we use them.
if considering_regions {
bty = bty.map_bound(|ty| {
tcx.fold_regions(ty, |r, current_depth| match r.kind() {
fold_regions(tcx, ty, |r, current_depth| match r.kind() {
ty::ReErased => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),

View file

@ -6,6 +6,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
@ -86,7 +87,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
}
}
// FIXME: This could use a real folder, I guess.
let remapped_wf_tys = tcx.fold_regions(
let remapped_wf_tys = fold_regions(
tcx,
tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(),
|region, _| {
// If `region` is a `ReLateParam` that is captured by the

View file

@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>(
// get a result which isn't correct for all monomorphizations.
match typing_env.typing_mode {
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { defining_opaque_types: _ } => false,
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => false,
ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
}
};

View file

@ -5,6 +5,7 @@ use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
};
@ -197,7 +198,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// We have entered some binders as we've walked into the
// bounds of the RPITIT. Shift these binders back out when
// constructing the top-level projection predicate.
let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
let shifted_alias_ty = fold_regions(self.tcx, unshifted_alias_ty, |re, depth| {
if let ty::ReBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return ty::Region::new_error_with_message(

View file

@ -49,7 +49,7 @@ use std::mem;
use rustc_index::{Idx, IndexVec};
use thin_vec::ThinVec;
use tracing::instrument;
use tracing::{debug, instrument};
use crate::data_structures::Lrc;
use crate::inherent::*;
@ -431,3 +431,75 @@ where
value.fold_with(&mut Shifter::new(cx, amount))
}
}
///////////////////////////////////////////////////////////////////////////
// Region folder
pub fn fold_regions<I: Interner, T>(
cx: I,
value: T,
mut f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region,
) -> T
where
T: TypeFoldable<I>,
{
value.fold_with(&mut RegionFolder::new(cx, &mut f))
}
/// Folds over the substructure of a type, visiting its component
/// types and all regions that occur *free* within it.
///
/// That is, function pointer types and trait object can introduce
/// new bound regions which are not visited by this visitors as
/// they are not free; only regions that occur free will be
/// visited by `fld_r`.
pub struct RegionFolder<'a, I: Interner> {
cx: I,
/// Stores the index of a binder *just outside* the stuff we have
/// visited. So this begins as INNERMOST; when we pass through a
/// binder, it is incremented (via `shift_in`).
current_index: ty::DebruijnIndex,
/// Callback invokes for each free region. The `DebruijnIndex`
/// points to the binder *just outside* the ones we have passed
/// through.
fold_region_fn: &'a mut (dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region + 'a),
}
impl<'a, I: Interner> RegionFolder<'a, I> {
#[inline]
pub fn new(
cx: I,
fold_region_fn: &'a mut dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region,
) -> RegionFolder<'a, I> {
RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn }
}
}
impl<'a, I: Interner> TypeFolder<I> for RegionFolder<'a, I> {
fn cx(&self) -> I {
self.cx
}
fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}
#[instrument(skip(self), level = "debug", ret)]
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region");
r
}
_ => {
debug!(?self.current_index, "folding free region");
(self.fold_region_fn)(r, self.current_index)
}
}
}
}

View file

@ -63,6 +63,12 @@ pub enum TypingMode<I: Interner> {
/// }
/// ```
Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
/// Any analysis after borrowck for a given body should be able to use all the
/// hidden types defined by borrowck, without being able to define any new ones.
///
/// This is currently only used by the new solver, but should be implemented in
/// the old solver as well.
PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes },
/// After analysis, mostly during codegen and MIR optimizations, we're able to
/// reveal all opaque types. As the concrete type should *never* be observable
/// directly by the user, this should not be used by checks which may expose
@ -85,6 +91,12 @@ impl<I: Interner> TypingMode<I> {
pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
}
pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: cx.opaque_types_defined_by(body_def_id),
}
}
}
pub trait InferCtxtLike: Sized {
@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized {
vid: ty::RegionVid,
) -> <Self::Interner as Interner>::Region;
fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
fn fresh_args_for_item(

View file

@ -136,9 +136,9 @@ where
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
Ok(a)
}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
structurally_relate_tys(relation, a, b)
}
TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
}
}