mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 22:05:14 +00:00
use deeply_normalize
for assumed_wf_types
This commit is contained in:
parent
d2c7449189
commit
5378f07d64
@ -4136,6 +4136,7 @@ dependencies = [
|
|||||||
name = "rustc_ty_utils"
|
name = "rustc_ty_utils"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
|
@ -224,7 +224,8 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||||||
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
|
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
|
|
||||||
|
let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
||||||
@ -395,7 +396,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
span: Span,
|
span: Span,
|
||||||
origin: &hir::OpaqueTyOrigin,
|
origin: &hir::OpaqueTyOrigin,
|
||||||
) {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let defining_use_anchor = match *origin {
|
let defining_use_anchor = match *origin {
|
||||||
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
|
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
|
||||||
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
|
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
|
||||||
@ -429,10 +430,10 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(ty_err) => {
|
Err(ty_err) => {
|
||||||
let ty_err = ty_err.to_string(tcx);
|
let ty_err = ty_err.to_string(tcx);
|
||||||
tcx.sess.delay_span_bug(
|
return Err(tcx.sess.delay_span_bug(
|
||||||
span,
|
span,
|
||||||
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
|
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +448,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
|
return Err(guar);
|
||||||
}
|
}
|
||||||
match origin {
|
match origin {
|
||||||
// Checked when type checking the function containing them.
|
// Checked when type checking the function containing them.
|
||||||
@ -461,14 +463,15 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
|
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
|
||||||
// Can have different predicates to their defining use
|
// Can have different predicates to their defining use
|
||||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||||
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
|
let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?;
|
||||||
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
|
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
|
||||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||||
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
|
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean up after ourselves
|
// Clean up after ourselves
|
||||||
let _ = infcx.take_opaque_types();
|
let _ = infcx.take_opaque_types();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_enum_of_nonnullable_ptr<'tcx>(
|
fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||||
|
@ -2121,7 +2121,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
|
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
|
||||||
|
|
||||||
let normalize_cause = ObligationCause::new(
|
let normalize_cause = ObligationCause::new(
|
||||||
impl_ty_span,
|
impl_ty_span,
|
||||||
|
@ -105,7 +105,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||||||
}
|
}
|
||||||
f(&mut wfcx);
|
f(&mut wfcx);
|
||||||
|
|
||||||
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
|
let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)
|
||||||
|
{
|
||||||
|
Ok(wf_types) => wf_types,
|
||||||
|
Err(_guar) => return,
|
||||||
|
};
|
||||||
|
|
||||||
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
|
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
|
||||||
|
|
||||||
let errors = wfcx.select_all_or_error();
|
let errors = wfcx.select_all_or_error();
|
||||||
|
@ -77,7 +77,7 @@ use rustc_infer::traits::specialization_graph::Node;
|
|||||||
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
|
||||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::Span;
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
|
use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
|
||||||
@ -113,7 +113,7 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
|
|||||||
let span = tcx.def_span(impl1_def_id);
|
let span = tcx.def_span(impl1_def_id);
|
||||||
check_has_items(tcx, impl1_def_id, impl2_node, span);
|
check_has_items(tcx, impl1_def_id, impl2_node, span);
|
||||||
|
|
||||||
if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
|
if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
|
||||||
let impl2_def_id = impl2_node.def_id();
|
let impl2_def_id = impl2_node.def_id();
|
||||||
debug!(?impl2_def_id, ?impl2_substs);
|
debug!(?impl2_def_id, ?impl2_substs);
|
||||||
|
|
||||||
@ -171,16 +171,14 @@ fn get_impl_substs(
|
|||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
impl1_def_id: LocalDefId,
|
impl1_def_id: LocalDefId,
|
||||||
impl2_node: Node,
|
impl2_node: Node,
|
||||||
) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> {
|
) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> {
|
||||||
let infcx = &tcx.infer_ctxt().build();
|
let infcx = &tcx.infer_ctxt().build();
|
||||||
let ocx = ObligationCtxt::new(infcx);
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
let param_env = tcx.param_env(impl1_def_id);
|
let param_env = tcx.param_env(impl1_def_id);
|
||||||
|
let impl1_span = tcx.def_span(impl1_def_id);
|
||||||
let assumed_wf_types =
|
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
|
||||||
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
|
|
||||||
|
|
||||||
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
|
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
|
||||||
let impl1_span = tcx.def_span(impl1_def_id);
|
|
||||||
let impl2_substs = translate_substs_with_cause(
|
let impl2_substs = translate_substs_with_cause(
|
||||||
infcx,
|
infcx,
|
||||||
param_env,
|
param_env,
|
||||||
@ -198,8 +196,8 @@ fn get_impl_substs(
|
|||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return None;
|
return Err(guar);
|
||||||
}
|
}
|
||||||
|
|
||||||
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
|
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
|
||||||
@ -207,10 +205,10 @@ fn get_impl_substs(
|
|||||||
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||||
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
|
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
|
||||||
let span = tcx.def_span(impl1_def_id);
|
let span = tcx.def_span(impl1_def_id);
|
||||||
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
||||||
return None;
|
return Err(guar);
|
||||||
};
|
};
|
||||||
Some((impl1_substs, impl2_substs))
|
Ok((impl1_substs, impl2_substs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of all of the unconstrained subst of the given impl.
|
/// Returns a list of all of the unconstrained subst of the given impl.
|
||||||
|
@ -881,7 +881,7 @@ rustc_queries! {
|
|||||||
///
|
///
|
||||||
/// Note that we've liberated the late bound regions of function signatures, so
|
/// Note that we've liberated the late bound regions of function signatures, so
|
||||||
/// this can not be used to check whether these types are well formed.
|
/// this can not be used to check whether these types are well formed.
|
||||||
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
|
query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||||
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +427,11 @@ fn prove_negated_obligation<'tcx>(
|
|||||||
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
|
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
|
||||||
|
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
|
let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
let outlives_env = OutlivesEnvironment::with_bounds(
|
let outlives_env = OutlivesEnvironment::with_bounds(
|
||||||
param_env,
|
param_env,
|
||||||
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
|
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
|
||||||
|
@ -4,6 +4,7 @@ use std::fmt::Debug;
|
|||||||
use super::TraitEngine;
|
use super::TraitEngine;
|
||||||
use super::{ChalkFulfillmentContext, FulfillmentContext};
|
use super::{ChalkFulfillmentContext, FulfillmentContext};
|
||||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||||
|
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
@ -24,7 +25,6 @@ use rustc_middle::ty::ToPredicate;
|
|||||||
use rustc_middle::ty::TypeFoldable;
|
use rustc_middle::ty::TypeFoldable;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_session::config::TraitSolver;
|
use rustc_session::config::TraitSolver;
|
||||||
use rustc_span::Span;
|
|
||||||
|
|
||||||
pub trait TraitEngineExt<'tcx> {
|
pub trait TraitEngineExt<'tcx> {
|
||||||
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
|
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
|
||||||
@ -198,17 +198,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn assumed_wf_types_and_report_errors(
|
||||||
|
&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
|
||||||
|
self.assumed_wf_types(param_env, def_id)
|
||||||
|
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn assumed_wf_types(
|
pub fn assumed_wf_types(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
span: Span,
|
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) -> FxIndexSet<Ty<'tcx>> {
|
) -> Result<FxIndexSet<Ty<'tcx>>, Vec<FulfillmentError<'tcx>>> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let assumed_wf_types = tcx.assumed_wf_types(def_id);
|
|
||||||
let mut implied_bounds = FxIndexSet::default();
|
let mut implied_bounds = FxIndexSet::default();
|
||||||
let cause = ObligationCause::misc(span, def_id);
|
let mut errors = Vec::new();
|
||||||
for ty in assumed_wf_types {
|
for &(ty, span) in tcx.assumed_wf_types(def_id) {
|
||||||
// FIXME(@lcnr): rustc currently does not check wf for types
|
// FIXME(@lcnr): rustc currently does not check wf for types
|
||||||
// pre-normalization, meaning that implied bounds are sometimes
|
// pre-normalization, meaning that implied bounds are sometimes
|
||||||
// incorrect. See #100910 for more details.
|
// incorrect. See #100910 for more details.
|
||||||
@ -221,10 +228,15 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
// sound and then uncomment this line again.
|
// sound and then uncomment this line again.
|
||||||
|
|
||||||
// implied_bounds.insert(ty);
|
// implied_bounds.insert(ty);
|
||||||
let normalized = self.normalize(&cause, param_env, ty);
|
let cause = ObligationCause::misc(span, def_id);
|
||||||
implied_bounds.insert(normalized);
|
match self.infcx.at(&cause, param_env).deeply_normalize(ty) {
|
||||||
|
// Insert well-formed types, ignoring duplicates.
|
||||||
|
Ok(normalized) => drop(implied_bounds.insert(normalized)),
|
||||||
|
Err(normalization_errors) => errors.extend(normalization_errors),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
implied_bounds
|
|
||||||
|
if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_canonicalized_query_response<T>(
|
pub fn make_canonicalized_query_response<T>(
|
||||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
itertools = "0.10.1"
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_errors = { path = "../rustc_errors" }
|
rustc_errors = { path = "../rustc_errors" }
|
||||||
|
@ -1,45 +1,56 @@
|
|||||||
use rustc_hir::{def::DefKind, def_id::DefId};
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
use rustc_span::Span;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { assumed_wf_types, ..*providers };
|
*providers = Providers { assumed_wf_types, ..*providers };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
|
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Fn => {
|
DefKind::Fn => {
|
||||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
let sig = tcx.fn_sig(def_id).subst_identity();
|
||||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
|
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||||
liberated_sig.inputs_and_output
|
tcx.arena.alloc_from_iter(itertools::zip_eq(
|
||||||
|
liberated_sig.inputs_and_output,
|
||||||
|
fn_sig_spans(tcx, def_id),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
DefKind::AssocFn => {
|
DefKind::AssocFn => {
|
||||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
let sig = tcx.fn_sig(def_id).subst_identity();
|
||||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
|
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||||
let mut assumed_wf_types: Vec<_> =
|
let mut assumed_wf_types: Vec<_> =
|
||||||
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
|
tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
|
||||||
assumed_wf_types.extend(liberated_sig.inputs_and_output);
|
assumed_wf_types.extend(itertools::zip_eq(
|
||||||
tcx.mk_type_list(&assumed_wf_types)
|
liberated_sig.inputs_and_output,
|
||||||
|
fn_sig_spans(tcx, def_id),
|
||||||
|
));
|
||||||
|
tcx.arena.alloc_slice(&assumed_wf_types)
|
||||||
}
|
}
|
||||||
DefKind::Impl { .. } => {
|
DefKind::Impl { .. } => {
|
||||||
match tcx.impl_trait_ref(def_id) {
|
// Trait arguments and the self type for trait impls or only the self type for
|
||||||
Some(trait_ref) => {
|
// inherent impls.
|
||||||
let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
|
let tys = match tcx.impl_trait_ref(def_id) {
|
||||||
tcx.mk_type_list(&types)
|
Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
|
||||||
|
None => vec![tcx.type_of(def_id).subst_identity()],
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut impl_spans = impl_spans(tcx, def_id);
|
||||||
|
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
|
||||||
}
|
}
|
||||||
// Only the impl self type
|
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
||||||
None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
|
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
|
||||||
}
|
|
||||||
}
|
|
||||||
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
|
|
||||||
DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
|
|
||||||
DefKind::TyAlias => ty::List::empty(),
|
DefKind::TyAlias => ty::List::empty(),
|
||||||
DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
|
DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
||||||
// Nested opaque types only occur in associated types:
|
// Nested opaque types only occur in associated types:
|
||||||
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
||||||
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
|
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
|
||||||
// and `&'static T`.
|
// and `&'static T`.
|
||||||
DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"),
|
DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
|
||||||
def_kind @ _ => {
|
def_kind @ _ => {
|
||||||
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
|
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
|
||||||
}
|
}
|
||||||
@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
|
|||||||
| DefKind::Generator => ty::List::empty(),
|
| DefKind::Generator => ty::List::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
|
||||||
|
let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id));
|
||||||
|
if let Some(decl) = node.fn_decl() {
|
||||||
|
decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
|
||||||
|
} else {
|
||||||
|
bug!("unexpected item for fn {def_id:?}: {node:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
|
||||||
|
let item = tcx.hir().expect_item(def_id);
|
||||||
|
if let hir::ItemKind::Impl(impl_) = item.kind {
|
||||||
|
let trait_args = impl_
|
||||||
|
.of_trait
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
|
||||||
|
.map(|arg| arg.span());
|
||||||
|
let dummy_spans_for_default_args =
|
||||||
|
impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
|
||||||
|
iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
|
||||||
|
} else {
|
||||||
|
bug!("unexpected item for impl {def_id:?}: {item:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user