move check_opaque_type_parameter_valid
This commit is contained in:
parent
abc838be13
commit
990201cb78
7 changed files with 189 additions and 182 deletions
|
@ -162,13 +162,6 @@ borrowck_opaque_type_lifetime_mismatch =
|
||||||
.prev_lifetime_label = lifetime `{$prev}` previously used here
|
.prev_lifetime_label = lifetime `{$prev}` previously used here
|
||||||
.note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
.note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||||
|
|
||||||
borrowck_opaque_type_non_generic_param =
|
|
||||||
expected generic {$kind} parameter, found `{$ty}`
|
|
||||||
.label = {STREQ($ty, "'static") ->
|
|
||||||
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
|
||||||
*[other] this generic parameter must be used with a generic {$kind} parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
borrowck_partial_var_move_by_use_in_closure =
|
borrowck_partial_var_move_by_use_in_closure =
|
||||||
variable {$is_partial ->
|
variable {$is_partial ->
|
||||||
[true] partially moved
|
[true] partially moved
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||||
use rustc_hir::OpaqueTyOrigin;
|
|
||||||
use rustc_hir::def_id::LocalDefId;
|
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
|
||||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
|
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
|
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
|
||||||
TypeVisitableExt, TypingMode, fold_regions,
|
|
||||||
};
|
};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
|
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
use super::RegionInferenceContext;
|
use super::RegionInferenceContext;
|
||||||
use crate::opaque_types::ConcreteOpaqueTypes;
|
use crate::opaque_types::ConcreteOpaqueTypes;
|
||||||
use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
|
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||||
use crate::universal_regions::RegionClassification;
|
use crate::universal_regions::RegionClassification;
|
||||||
|
|
||||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
|
@ -289,156 +283,3 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
definition_ty
|
definition_ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
|
|
||||||
///
|
|
||||||
/// [rustc-dev-guide chapter]:
|
|
||||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
|
||||||
fn check_opaque_type_parameter_valid<'tcx>(
|
|
||||||
infcx: &InferCtxt<'tcx>,
|
|
||||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
|
||||||
let tcx = infcx.tcx;
|
|
||||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
|
||||||
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
|
|
||||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
|
||||||
|
|
||||||
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
|
|
||||||
let arg_is_param = match arg.unpack() {
|
|
||||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
|
||||||
GenericArgKind::Lifetime(lt) => {
|
|
||||||
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|
|
||||||
|| (lt.is_static() && opaque_env.param_equal_static(i))
|
|
||||||
}
|
|
||||||
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
|
|
||||||
};
|
|
||||||
|
|
||||||
if arg_is_param {
|
|
||||||
// Register if the same lifetime appears multiple times in the generic args.
|
|
||||||
// There is an exception when the opaque type *requires* the lifetimes to be equal.
|
|
||||||
// See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
|
|
||||||
let seen_where = seen_params.entry(arg).or_default();
|
|
||||||
if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
|
|
||||||
seen_where.push(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
|
||||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
|
||||||
let kind = opaque_param.kind.descr();
|
|
||||||
|
|
||||||
opaque_env.param_is_error(i)?;
|
|
||||||
|
|
||||||
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
|
||||||
ty: arg,
|
|
||||||
kind,
|
|
||||||
span,
|
|
||||||
param_span: tcx.def_span(opaque_param.def_id),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (_, indices) in seen_params {
|
|
||||||
if indices.len() > 1 {
|
|
||||||
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
|
||||||
let spans: Vec<_> = indices
|
|
||||||
.into_iter()
|
|
||||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
|
||||||
.collect();
|
|
||||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
|
||||||
return Err(infcx
|
|
||||||
.dcx()
|
|
||||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
|
||||||
.with_span_note(spans, format!("{descr} used multiple times"))
|
|
||||||
.emit());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes if an opaque type requires a lifetime parameter to be equal to
|
|
||||||
/// another one or to the `'static` lifetime.
|
|
||||||
/// These requirements are derived from the explicit and implied bounds.
|
|
||||||
struct LazyOpaqueTyEnv<'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
|
|
||||||
/// Equal parameters will have the same name. Computed Lazily.
|
|
||||||
/// Example:
|
|
||||||
/// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
|
|
||||||
/// Identity args: `['a, 'b, 'c]`
|
|
||||||
/// Canonical args: `['static, 'b, 'b]`
|
|
||||||
canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> LazyOpaqueTyEnv<'tcx> {
|
|
||||||
fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
|
||||||
Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_equal_static(&self, param_index: usize) -> bool {
|
|
||||||
self.get_canonical_args()[param_index].expect_region().is_static()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn params_equal(&self, param1: usize, param2: usize) -> bool {
|
|
||||||
let canonical_args = self.get_canonical_args();
|
|
||||||
canonical_args[param1] == canonical_args[param2]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
|
|
||||||
self.get_canonical_args()[param_index].error_reported()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
|
|
||||||
if let Some(&canonical_args) = self.canonical_args.get() {
|
|
||||||
return canonical_args;
|
|
||||||
}
|
|
||||||
|
|
||||||
let &Self { tcx, def_id, .. } = self;
|
|
||||||
let origin = tcx.local_opaque_ty_origin(def_id);
|
|
||||||
let parent = match origin {
|
|
||||||
OpaqueTyOrigin::FnReturn { parent, .. }
|
|
||||||
| OpaqueTyOrigin::AsyncFn { parent, .. }
|
|
||||||
| OpaqueTyOrigin::TyAlias { parent, .. } => parent,
|
|
||||||
};
|
|
||||||
let param_env = tcx.param_env(parent);
|
|
||||||
let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
|
|
||||||
tcx,
|
|
||||||
def_id.to_def_id(),
|
|
||||||
|param, _| {
|
|
||||||
tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
|
|
||||||
// in a body here.
|
|
||||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
|
||||||
|
|
||||||
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
|
|
||||||
tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
|
|
||||||
Default::default()
|
|
||||||
});
|
|
||||||
let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
|
|
||||||
|
|
||||||
let mut seen = vec![tcx.lifetimes.re_static];
|
|
||||||
let canonical_args = fold_regions(tcx, args, |r1, _| {
|
|
||||||
if r1.is_error() {
|
|
||||||
r1
|
|
||||||
} else if let Some(&r2) = seen.iter().find(|&&r2| {
|
|
||||||
let free_regions = outlives_env.free_region_map();
|
|
||||||
free_regions.sub_free_regions(tcx, r1, r2)
|
|
||||||
&& free_regions.sub_free_regions(tcx, r2, r1)
|
|
||||||
}) {
|
|
||||||
r2
|
|
||||||
} else {
|
|
||||||
seen.push(r1);
|
|
||||||
r1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.canonical_args.set(canonical_args).unwrap();
|
|
||||||
canonical_args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -294,17 +294,6 @@ pub(crate) struct MoveBorrow<'a> {
|
||||||
pub borrow_span: Span,
|
pub borrow_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(borrowck_opaque_type_non_generic_param, code = E0792)]
|
|
||||||
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
|
||||||
pub ty: GenericArg<'tcx>,
|
|
||||||
pub kind: &'a str,
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
#[label]
|
|
||||||
pub param_span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(borrowck_opaque_type_lifetime_mismatch)]
|
#[diag(borrowck_opaque_type_lifetime_mismatch)]
|
||||||
pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> {
|
pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> {
|
||||||
|
|
|
@ -264,8 +264,15 @@ trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge
|
||||||
trait_selection_oc_no_else = `if` may be missing an `else` clause
|
trait_selection_oc_no_else = `if` may be missing an `else` clause
|
||||||
trait_selection_oc_try_compat = `?` operator has incompatible types
|
trait_selection_oc_try_compat = `?` operator has incompatible types
|
||||||
trait_selection_oc_type_compat = type not compatible with trait
|
trait_selection_oc_type_compat = type not compatible with trait
|
||||||
|
|
||||||
trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
|
trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
|
||||||
.label = opaque type defined here
|
.label = opaque type defined here
|
||||||
|
trait_selection_opaque_type_non_generic_param =
|
||||||
|
expected generic {$kind} parameter, found `{$ty}`
|
||||||
|
.label = {STREQ($ty, "'static") ->
|
||||||
|
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||||
|
*[other] this generic parameter must be used with a generic {$kind} parameter
|
||||||
|
}
|
||||||
|
|
||||||
trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
|
trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
|
||||||
trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content...
|
trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content...
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
|
||||||
use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
|
use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
|
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
|
||||||
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt};
|
||||||
use rustc_span::{BytePos, Ident, Span, Symbol, kw};
|
use rustc_span::{BytePos, Ident, Span, Symbol, kw};
|
||||||
|
|
||||||
use crate::error_reporting::infer::ObligationCauseAsDiagArg;
|
use crate::error_reporting::infer::ObligationCauseAsDiagArg;
|
||||||
|
@ -1922,3 +1922,14 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)]
|
||||||
|
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
||||||
|
pub ty: GenericArg<'tcx>,
|
||||||
|
pub kind: &'a str,
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[label]
|
||||||
|
pub param_span: Span,
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
pub mod error_reporting;
|
pub mod error_reporting;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod infer;
|
pub mod infer;
|
||||||
|
pub mod opaque_types;
|
||||||
pub mod regions;
|
pub mod regions;
|
||||||
pub mod solve;
|
pub mod solve;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
165
compiler/rustc_trait_selection/src/opaque_types.rs
Normal file
165
compiler/rustc_trait_selection/src/opaque_types.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
use rustc_hir::OpaqueTyOrigin;
|
||||||
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
|
use rustc_middle::ty::{
|
||||||
|
self, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt,
|
||||||
|
TypingMode, fold_regions,
|
||||||
|
};
|
||||||
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
|
|
||||||
|
use crate::errors::NonGenericOpaqueTypeParam;
|
||||||
|
use crate::regions::OutlivesEnvironmentBuildExt;
|
||||||
|
use crate::traits::ObligationCtxt;
|
||||||
|
|
||||||
|
/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
|
||||||
|
///
|
||||||
|
/// [rustc-dev-guide chapter]:
|
||||||
|
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||||
|
pub fn check_opaque_type_parameter_valid<'tcx>(
|
||||||
|
infcx: &InferCtxt<'tcx>,
|
||||||
|
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
|
let tcx = infcx.tcx;
|
||||||
|
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||||
|
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
|
||||||
|
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||||
|
|
||||||
|
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
|
||||||
|
let arg_is_param = match arg.unpack() {
|
||||||
|
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||||
|
GenericArgKind::Lifetime(lt) => {
|
||||||
|
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|
||||||
|
|| (lt.is_static() && opaque_env.param_equal_static(i))
|
||||||
|
}
|
||||||
|
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
|
||||||
|
};
|
||||||
|
|
||||||
|
if arg_is_param {
|
||||||
|
// Register if the same lifetime appears multiple times in the generic args.
|
||||||
|
// There is an exception when the opaque type *requires* the lifetimes to be equal.
|
||||||
|
// See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
|
||||||
|
let seen_where = seen_params.entry(arg).or_default();
|
||||||
|
if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
|
||||||
|
seen_where.push(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||||
|
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||||
|
let kind = opaque_param.kind.descr();
|
||||||
|
|
||||||
|
opaque_env.param_is_error(i)?;
|
||||||
|
|
||||||
|
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||||
|
ty: arg,
|
||||||
|
kind,
|
||||||
|
span,
|
||||||
|
param_span: tcx.def_span(opaque_param.def_id),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, indices) in seen_params {
|
||||||
|
if indices.len() > 1 {
|
||||||
|
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
||||||
|
let spans: Vec<_> = indices
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||||
|
.collect();
|
||||||
|
return Err(infcx
|
||||||
|
.dcx()
|
||||||
|
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||||
|
.with_span_note(spans, format!("{descr} used multiple times"))
|
||||||
|
.emit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes if an opaque type requires a lifetime parameter to be equal to
|
||||||
|
/// another one or to the `'static` lifetime.
|
||||||
|
/// These requirements are derived from the explicit and implied bounds.
|
||||||
|
struct LazyOpaqueTyEnv<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
|
||||||
|
/// Equal parameters will have the same name. Computed Lazily.
|
||||||
|
/// Example:
|
||||||
|
/// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
|
||||||
|
/// Identity args: `['a, 'b, 'c]`
|
||||||
|
/// Canonical args: `['static, 'b, 'b]`
|
||||||
|
canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LazyOpaqueTyEnv<'tcx> {
|
||||||
|
fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||||
|
Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_equal_static(&self, param_index: usize) -> bool {
|
||||||
|
self.get_canonical_args()[param_index].expect_region().is_static()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn params_equal(&self, param1: usize, param2: usize) -> bool {
|
||||||
|
let canonical_args = self.get_canonical_args();
|
||||||
|
canonical_args[param1] == canonical_args[param2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
|
||||||
|
self.get_canonical_args()[param_index].error_reported()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
|
||||||
|
if let Some(&canonical_args) = self.canonical_args.get() {
|
||||||
|
return canonical_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
let &Self { tcx, def_id, .. } = self;
|
||||||
|
let origin = tcx.local_opaque_ty_origin(def_id);
|
||||||
|
let parent = match origin {
|
||||||
|
OpaqueTyOrigin::FnReturn { parent, .. }
|
||||||
|
| OpaqueTyOrigin::AsyncFn { parent, .. }
|
||||||
|
| OpaqueTyOrigin::TyAlias { parent, .. } => parent,
|
||||||
|
};
|
||||||
|
let param_env = tcx.param_env(parent);
|
||||||
|
let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
|
||||||
|
tcx,
|
||||||
|
def_id.to_def_id(),
|
||||||
|
|param, _| {
|
||||||
|
tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
|
||||||
|
// in a body here.
|
||||||
|
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
|
||||||
|
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
|
||||||
|
tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
|
||||||
|
Default::default()
|
||||||
|
});
|
||||||
|
let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
|
||||||
|
|
||||||
|
let mut seen = vec![tcx.lifetimes.re_static];
|
||||||
|
let canonical_args = fold_regions(tcx, args, |r1, _| {
|
||||||
|
if r1.is_error() {
|
||||||
|
r1
|
||||||
|
} else if let Some(&r2) = seen.iter().find(|&&r2| {
|
||||||
|
let free_regions = outlives_env.free_region_map();
|
||||||
|
free_regions.sub_free_regions(tcx, r1, r2)
|
||||||
|
&& free_regions.sub_free_regions(tcx, r2, r1)
|
||||||
|
}) {
|
||||||
|
r2
|
||||||
|
} else {
|
||||||
|
seen.push(r1);
|
||||||
|
r1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.canonical_args.set(canonical_args).unwrap();
|
||||||
|
canonical_args
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue