1
Fork 0

Rollup merge of #89915 - jackh726:outlives_cleanup, r=nikomatsakis

Some outlives cleanup

No semantic changes here, only moving code around + using `LocalDefId` instead of `HirId`

r? ````@nikomatsakis````
This commit is contained in:
Matthias Krüger 2021-10-16 08:02:25 +02:00 committed by GitHub
commit 502d57b32d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 100 additions and 115 deletions

View file

@ -2,10 +2,10 @@
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that // refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
// RFC for reference. // RFC for reference.
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::sso::SsoHashSet;
use smallvec::SmallVec; use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use smallvec::{smallvec, SmallVec};
#[derive(Debug)] #[derive(Debug)]
pub enum Component<'tcx> { pub enum Component<'tcx> {
@ -47,14 +47,16 @@ pub enum Component<'tcx> {
EscapingProjection(Vec<Component<'tcx>>), EscapingProjection(Vec<Component<'tcx>>),
} }
impl<'tcx> TyCtxt<'tcx> { /// Push onto `out` all the things that must outlive `'a` for the condition
/// Push onto `out` all the things that must outlive `'a` for the condition /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. pub fn push_outlives_components(
pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) { tcx: TyCtxt<'tcx>,
let mut visited = SsoHashSet::new(); ty0: Ty<'tcx>,
compute_components(self, ty0, out, &mut visited); out: &mut SmallVec<[Component<'tcx>; 4]>,
debug!("components({:?}) = {:?}", ty0, out); ) {
} let mut visited = SsoHashSet::new();
compute_components(tcx, ty0, out, &mut visited);
debug!("components({:?}) = {:?}", ty0, out);
} }
fn compute_components( fn compute_components(

View file

@ -1,5 +1,6 @@
//! Various code related to computing outlives relations. //! Various code related to computing outlives relations.
pub mod components;
pub mod env; pub mod env;
pub mod obligations; pub mod obligations;
pub mod verify; pub mod verify;

View file

@ -1,5 +1,5 @@
//! Code that handles "type-outlives" constraints like `T: 'a`. This //! Code that handles "type-outlives" constraints like `T: 'a`. This
//! is based on the `push_outlives_components` function defined on the tcx, //! is based on the `push_outlives_components` function defined in rustc_infer,
//! but it adds a bit of heuristics on top, in particular to deal with //! but it adds a bit of heuristics on top, in particular to deal with
//! associated types and projections. //! associated types and projections.
//! //!
@ -59,13 +59,13 @@
//! might later infer `?U` to something like `&'b u32`, which would //! might later infer `?U` to something like `&'b u32`, which would
//! imply that `'b: 'a`. //! imply that `'b: 'a`.
use crate::infer::outlives::components::{push_outlives_components, Component};
use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::outlives::verify::VerifyBoundCx;
use crate::infer::{ use crate::infer::{
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
}; };
use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
@ -271,7 +271,7 @@ where
assert!(!ty.has_escaping_bound_vars()); assert!(!ty.has_escaping_bound_vars());
let mut components = smallvec![]; let mut components = smallvec![];
self.tcx.push_outlives_components(ty, &mut components); push_outlives_components(self.tcx, ty, &mut components);
self.components_must_outlive(origin, &components, region); self.components_must_outlive(origin, &components, region);
} }

View file

@ -1,8 +1,8 @@
use smallvec::smallvec; use smallvec::smallvec;
use crate::infer::outlives::components::{push_outlives_components, Component};
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
@ -200,7 +200,7 @@ impl Elaborator<'tcx> {
let visited = &mut self.visited; let visited = &mut self.visited;
let mut components = smallvec![]; let mut components = smallvec![];
tcx.push_outlives_components(ty_max, &mut components); push_outlives_components(tcx, ty_max, &mut components);
self.stack.extend( self.stack.extend(
components components
.into_iter() .into_iter()

View file

@ -92,7 +92,6 @@ pub mod fold;
pub mod inhabitedness; pub mod inhabitedness;
pub mod layout; pub mod layout;
pub mod normalize_erasing_regions; pub mod normalize_erasing_regions;
pub mod outlives;
pub mod print; pub mod print;
pub mod query; pub mod query;
pub mod relate; pub mod relate;

View file

@ -1,12 +1,8 @@
use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt}; use crate::traits::{self, TraitEngine, TraitEngineExt};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_middle::arena::ArenaAllocatable; use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
@ -180,48 +176,3 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
) )
} }
} }
pub trait OutlivesEnvironmentExt<'tcx> {
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
);
}
impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
/// This method adds "implied bounds" into the outlives environment.
/// Implied bounds are outlives relationships that we can deduce
/// on the basis that certain types must be well-formed -- these are
/// either the types that appear in the function signature or else
/// the input types to an impl. For example, if you have a function
/// like
///
/// ```
/// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
/// ```
///
/// we can assume in the caller's body that `'b: 'a` and that `T:
/// 'b` (and hence, transitively, that `T: 'a`). This method would
/// add those assumptions into the outlives-environment.
///
/// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
) {
debug!("add_implied_bounds()");
for ty in fn_sig_tys {
let ty = infcx.resolve_vars_if_possible(ty);
debug!("add_implied_bounds: ty = {}", ty);
let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
self.add_outlives_bounds(Some(infcx), implied_bounds)
}
}
}

View file

@ -9,7 +9,6 @@ pub mod dropck_outlives;
pub mod evaluate_obligation; pub mod evaluate_obligation;
pub mod method_autoderef; pub mod method_autoderef;
pub mod normalize; pub mod normalize;
pub mod outlives_bounds;
pub mod type_op; pub mod type_op;
pub use rustc_middle::traits::query::*; pub use rustc_middle::traits::query::*;

View file

@ -1,6 +1,6 @@
use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
use crate::traits::query::outlives_bounds::OutlivesBound;
use crate::traits::query::Fallible; use crate::traits::query::Fallible;
use rustc_infer::traits::query::OutlivesBound;
use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]

View file

@ -4,14 +4,14 @@
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::infer::canonical::{self, Canonical}; use rustc_infer::infer::canonical::{self, Canonical};
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::query::OutlivesBound;
use rustc_infer::traits::TraitEngineExt as _; use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::source_map::DUMMY_SP; use rustc_span::source_map::DUMMY_SP;
use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc_trait_selection::traits::wf; use rustc_trait_selection::traits::wf;
use rustc_trait_selection::traits::FulfillmentContext; use rustc_trait_selection::traits::FulfillmentContext;
@ -118,7 +118,7 @@ fn compute_implied_outlives_bounds<'tcx>(
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => { ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
let ty_a = infcx.resolve_vars_if_possible(ty_a); let ty_a = infcx.resolve_vars_if_possible(ty_a);
let mut components = smallvec![]; let mut components = smallvec![];
tcx.push_outlives_components(ty_a, &mut components); push_outlives_components(tcx, ty_a, &mut components);
implied_bounds_from_components(r_b, components) implied_bounds_from_components(r_b, components)
} }
}, },

View file

@ -76,19 +76,19 @@ use crate::check::dropck;
use crate::check::FnCtxt; use crate::check::FnCtxt;
use crate::mem_categorization as mc; use crate::mem_categorization as mc;
use crate::middle::region; use crate::middle::region;
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_data_structures::stable_set::FxHashSet; use rustc_data_structures::stable_set::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::PatKind; use rustc_hir::PatKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, RegionObligation, RegionckMode}; use rustc_infer::infer::{self, InferCtxt, RegionObligation, RegionckMode};
use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
use rustc_middle::ty::adjustment; use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::infer::OutlivesEnvironmentExt; use rustc_trait_selection::opaque_types::InferCtxtExt as _;
use rustc_trait_selection::opaque_types::InferCtxtExt;
use std::ops::Deref; use std::ops::Deref;
// a variation on try that just returns unit // a variation on try that just returns unit
@ -104,6 +104,51 @@ macro_rules! ignore_err {
}; };
} }
trait OutlivesEnvironmentExt<'tcx> {
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
);
}
impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
/// This method adds "implied bounds" into the outlives environment.
/// Implied bounds are outlives relationships that we can deduce
/// on the basis that certain types must be well-formed -- these are
/// either the types that appear in the function signature or else
/// the input types to an impl. For example, if you have a function
/// like
///
/// ```
/// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
/// ```
///
/// we can assume in the caller's body that `'b: 'a` and that `T:
/// 'b` (and hence, transitively, that `T: 'a`). This method would
/// add those assumptions into the outlives-environment.
///
/// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
) {
debug!("add_implied_bounds()");
for ty in fn_sig_tys {
let ty = infcx.resolve_vars_if_possible(ty);
debug!("add_implied_bounds: ty = {}", ty);
let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
self.add_outlives_bounds(Some(infcx), implied_bounds)
}
}
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// PUBLIC ENTRY POINTS // PUBLIC ENTRY POINTS

View file

@ -142,23 +142,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
} }
} }
hir::ItemKind::Fn(ref sig, ..) => { hir::ItemKind::Fn(ref sig, ..) => {
check_item_fn(tcx, item.hir_id(), item.ident, item.span, sig.decl); check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl);
} }
hir::ItemKind::Static(ty, ..) => { hir::ItemKind::Static(ty, ..) => {
check_item_type(tcx, item.hir_id(), ty.span, false); check_item_type(tcx, item.def_id, ty.span, false);
} }
hir::ItemKind::Const(ty, ..) => { hir::ItemKind::Const(ty, ..) => {
check_item_type(tcx, item.hir_id(), ty.span, false); check_item_type(tcx, item.def_id, ty.span, false);
} }
hir::ItemKind::ForeignMod { items, .. } => { hir::ItemKind::ForeignMod { items, .. } => {
for it in items.iter() { for it in items.iter() {
let it = tcx.hir().foreign_item(it.id); let it = tcx.hir().foreign_item(it.id);
match it.kind { match it.kind {
hir::ForeignItemKind::Fn(decl, ..) => { hir::ForeignItemKind::Fn(decl, ..) => {
check_item_fn(tcx, it.hir_id(), it.ident, it.span, decl) check_item_fn(tcx, it.def_id, it.ident, it.span, decl)
} }
hir::ForeignItemKind::Static(ty, ..) => { hir::ForeignItemKind::Static(ty, ..) => {
check_item_type(tcx, it.hir_id(), ty.span, true) check_item_type(tcx, it.def_id, ty.span, true)
} }
hir::ForeignItemKind::Type => (), hir::ForeignItemKind::Type => (),
} }
@ -199,7 +199,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
_ => (None, trait_item.span), _ => (None, trait_item.span),
}; };
check_object_unsafe_self_trait_by_name(tcx, trait_item); check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, trait_item.hir_id(), span, method_sig); check_associated_item(tcx, trait_item.def_id, span, method_sig);
let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id); let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
let encl_trait = tcx.hir().expect_item(encl_trait_hir_id); let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
@ -327,7 +327,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
_ => (None, impl_item.span), _ => (None, impl_item.span),
}; };
check_associated_item(tcx, impl_item.hir_id(), span, method_sig); check_associated_item(tcx, impl_item.def_id, span, method_sig);
} }
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@ -437,13 +437,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))] #[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
fn check_associated_item( fn check_associated_item(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
item_id: hir::HirId, item_id: LocalDefId,
span: Span, span: Span,
sig_if_method: Option<&hir::FnSig<'_>>, sig_if_method: Option<&hir::FnSig<'_>>,
) { ) {
let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))); let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id)));
for_id(tcx, item_id, span).with_fcx(|fcx| { for_id(tcx, item_id, span).with_fcx(|fcx| {
let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); let item = fcx.tcx.associated_item(item_id);
let (mut implied_bounds, self_ty) = match item.container { let (mut implied_bounds, self_ty) = match item.container {
ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param), ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param),
@ -455,11 +455,7 @@ fn check_associated_item(
match item.kind { match item.kind {
ty::AssocKind::Const => { ty::AssocKind::Const => {
let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.tcx.type_of(item.def_id);
let ty = fcx.normalize_associated_types_in_wf( let ty = fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id));
span,
ty,
WellFormedLoc::Ty(item_id.expect_owner()),
);
fcx.register_wf_obligation(ty.into(), span, code.clone()); fcx.register_wf_obligation(ty.into(), span, code.clone());
} }
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
@ -481,11 +477,8 @@ fn check_associated_item(
} }
if item.defaultness.has_value() { if item.defaultness.has_value() {
let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.tcx.type_of(item.def_id);
let ty = fcx.normalize_associated_types_in_wf( let ty =
span, fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id));
ty,
WellFormedLoc::Ty(item_id.expect_owner()),
);
fcx.register_wf_obligation(ty.into(), span, code.clone()); fcx.register_wf_obligation(ty.into(), span, code.clone());
} }
} }
@ -496,14 +489,13 @@ fn check_associated_item(
} }
fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> { fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
for_id(tcx, item.hir_id(), item.span) for_id(tcx, item.def_id, item.span)
} }
fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> { fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> {
let def_id = tcx.hir().local_def_id(id);
CheckWfFcxBuilder { CheckWfFcxBuilder {
inherited: Inherited::build(tcx, def_id), inherited: Inherited::build(tcx, def_id),
id, id: hir::HirId::make_owner(def_id),
span, span,
param_env: tcx.param_env(def_id), param_env: tcx.param_env(def_id),
} }
@ -665,13 +657,12 @@ fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span
fn check_item_fn( fn check_item_fn(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
item_id: hir::HirId, def_id: LocalDefId,
ident: Ident, ident: Ident,
span: Span, span: Span,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
) { ) {
for_id(tcx, item_id, span).with_fcx(|fcx| { for_id(tcx, def_id, span).with_fcx(|fcx| {
let def_id = tcx.hir().local_def_id(item_id);
let sig = tcx.fn_sig(def_id); let sig = tcx.fn_sig(def_id);
let mut implied_bounds = FxHashSet::default(); let mut implied_bounds = FxHashSet::default();
check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds); check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
@ -679,16 +670,12 @@ fn check_item_fn(
}) })
} }
fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_foreign_ty: bool) { fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
debug!("check_item_type: {:?}", item_id); debug!("check_item_type: {:?}", item_id);
for_id(tcx, item_id, ty_span).with_fcx(|fcx| { for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
let ty = tcx.type_of(tcx.hir().local_def_id(item_id)); let ty = tcx.type_of(item_id);
let item_ty = fcx.normalize_associated_types_in_wf( let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, WellFormedLoc::Ty(item_id));
ty_span,
ty,
WellFormedLoc::Ty(item_id.expect_owner()),
);
let mut forbid_unsized = true; let mut forbid_unsized = true;
if allow_foreign_ty { if allow_foreign_ty {
@ -701,7 +688,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
fcx.register_wf_obligation( fcx.register_wf_obligation(
item_ty.into(), item_ty.into(),
ty_span, ty_span,
ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))), ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id))),
); );
if forbid_unsized { if forbid_unsized {
fcx.register_bound( fcx.register_bound(

View file

@ -9,6 +9,7 @@ use rustc_span::Span;
mod explicit; mod explicit;
mod implicit_infer; mod implicit_infer;
crate mod outlives_bounds;
/// Code to write unit test for outlives. /// Code to write unit test for outlives.
pub mod test; pub mod test;
mod utils; mod utils;

View file

@ -1,11 +1,11 @@
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
use crate::traits::query::NoSolution;
use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::traits::TraitEngineExt as _; use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_trait_selection::infer::canonical::OriginalQueryValues;
use rustc_trait_selection::infer::InferCtxt;
use rustc_trait_selection::traits::query::NoSolution;
use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine};
pub use rustc_middle::traits::query::OutlivesBound; pub use rustc_middle::traits::query::OutlivesBound;

View file

@ -1,4 +1,4 @@
use rustc_middle::ty::outlives::Component; use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, Region, RegionKind, Ty, TyCtxt}; use rustc_middle::ty::{self, Region, RegionKind, Ty, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
@ -35,7 +35,7 @@ pub fn insert_outlives_predicate<'tcx>(
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
// we would want to add `U: 'outlived_region` // we would want to add `U: 'outlived_region`
let mut components = smallvec![]; let mut components = smallvec![];
tcx.push_outlives_components(ty, &mut components); push_outlives_components(tcx, ty, &mut components);
for component in components { for component in components {
match component { match component {
Component::Region(r) => { Component::Region(r) => {