Auto merge of #92805 - BoxyUwU:revert-lazy-anon-const-substs, r=lcnr
partially revertish `lazily "compute" anon const default substs` reverts #87280 except for some of the changes around `ty::Unevaluated` having a visitor and a generic for promoted why revert: <https://github.com/rust-lang/rust/pull/92805#issuecomment-1010736049> r? `@lcnr`
This commit is contained in:
commit
7be8693984
123 changed files with 405 additions and 886 deletions
|
@ -388,7 +388,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
if self.is_object && has_default {
|
||||
let default_ty = tcx.at(self.span).type_of(param.def_id);
|
||||
let self_param = tcx.types.self_param;
|
||||
if default_ty.walk(tcx).any(|arg| arg == self_param.into()) {
|
||||
if default_ty.walk().any(|arg| arg == self_param.into()) {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return true;
|
||||
|
@ -1378,7 +1378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// A `Self` within the original bound will be substituted with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self =
|
||||
pred.skip_binder().ty.walk(tcx).any(|arg| arg == dummy_self.into());
|
||||
pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
|
||||
|
||||
// If the projection output contains `Self`, force the user to
|
||||
// elaborate it explicitly to avoid a lot of complexity.
|
||||
|
@ -2225,7 +2225,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.prohibit_generics(path.segments);
|
||||
// Try to evaluate any array length constants.
|
||||
let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
|
||||
if forbid_generic && normalized_ty.definitely_needs_subst(tcx) {
|
||||
if forbid_generic && normalized_ty.needs_subst() {
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
path.span,
|
||||
"generic `Self` types are currently not permitted in anonymous constants",
|
||||
|
|
|
@ -462,17 +462,14 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
|
|||
debug!(?item, ?span);
|
||||
|
||||
struct FoundParentLifetime;
|
||||
struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
|
||||
struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics);
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
|
||||
type BreakTy = FoundParentLifetime;
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.0)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("FindParentLifetimeVisitor: r={:?}", r);
|
||||
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
|
||||
if *index < self.1.parent_count as u32 {
|
||||
if *index < self.0.parent_count as u32 {
|
||||
return ControlFlow::Break(FoundParentLifetime);
|
||||
} else {
|
||||
return ControlFlow::CONTINUE;
|
||||
|
@ -502,16 +499,13 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
|
|||
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
|
||||
type BreakTy = Ty<'tcx>;
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.tcx)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
|
||||
if t == self.opaque_identity_ty {
|
||||
ControlFlow::CONTINUE
|
||||
} else {
|
||||
t.super_visit_with(&mut FindParentLifetimeVisitor(self.tcx, self.generics))
|
||||
t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics))
|
||||
.map_break(|FoundParentLifetime| t)
|
||||
}
|
||||
}
|
||||
|
@ -1381,7 +1375,7 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
for leaf in ty.walk(tcx) {
|
||||
for leaf in ty.walk() {
|
||||
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
||||
if let ty::Param(param) = leaf_ty.kind() {
|
||||
debug!("found use of ty param {:?}", param);
|
||||
|
@ -1479,10 +1473,6 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
|
|||
{
|
||||
struct OpaqueTypeCollector(Vec<DefId>);
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector {
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
// Default anon const substs cannot contain opaque types.
|
||||
None
|
||||
}
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *t.kind() {
|
||||
ty::Opaque(def, _) => {
|
||||
|
|
|
@ -235,7 +235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
debug!("fcx {}", self.tag());
|
||||
|
||||
if self.can_contain_user_lifetime_bounds((substs, user_self_ty)) {
|
||||
if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
|
||||
let canonicalized = self.infcx.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
def_id,
|
||||
UserSubsts { substs, user_self_ty },
|
||||
|
@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty = self.to_ty(ast_ty);
|
||||
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
|
||||
|
||||
if self.can_contain_user_lifetime_bounds(ty) {
|
||||
if Self::can_contain_user_lifetime_bounds(ty) {
|
||||
let c_ty = self.infcx.canonicalize_response(UserType::Ty(ty));
|
||||
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
|
||||
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
|
||||
|
@ -541,11 +541,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// reader, although I have my doubts). Also pass in types with inference
|
||||
// types, because they may be repeated. Other sorts of things are already
|
||||
// sufficiently enforced with erased regions. =)
|
||||
fn can_contain_user_lifetime_bounds<T>(&self, t: T) -> bool
|
||||
fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types()
|
||||
t.has_free_regions() || t.has_projections() || t.has_infer_types()
|
||||
}
|
||||
|
||||
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
|
|
|
@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty = self.resolve_vars_if_possible(ty);
|
||||
// We walk the argument type because the argument's type could have
|
||||
// been `Option<T>`, but the `FulfillmentError` references `T`.
|
||||
if ty.walk(self.tcx).any(|arg| arg == self_) { Some(i) } else { None }
|
||||
if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
|
||||
})
|
||||
.collect::<Vec<usize>>();
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
if let Some(missing_trait) = missing_trait {
|
||||
let mut visitor = TypeParamVisitor(self.tcx, vec![]);
|
||||
let mut visitor = TypeParamVisitor(vec![]);
|
||||
visitor.visit_ty(lhs_ty);
|
||||
|
||||
if op.node == hir::BinOpKind::Add
|
||||
|
@ -434,7 +434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// This has nothing here because it means we did string
|
||||
// concatenation (e.g., "Hello " + "World!"). This means
|
||||
// we don't want the note in the else clause to be emitted
|
||||
} else if let [ty] = &visitor.1[..] {
|
||||
} else if let [ty] = &visitor.0[..] {
|
||||
if let ty::Param(p) = *ty.kind() {
|
||||
// Check if the method would be found if the type param wasn't
|
||||
// involved. If so, it means that adding a trait bound to the param is
|
||||
|
@ -991,15 +991,12 @@ fn suggest_constraining_param(
|
|||
}
|
||||
}
|
||||
|
||||
struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
|
||||
struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.0)
|
||||
}
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::Param(_) = ty.kind() {
|
||||
self.1.push(ty);
|
||||
self.0.push(ty);
|
||||
}
|
||||
ty.super_visit_with(self)
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ fn check_gat_where_clauses(
|
|||
// of the function signature. In our example, the GAT in the return
|
||||
// type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
|
||||
let (regions, types) =
|
||||
GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
|
||||
GATSubstCollector::visit(trait_item.def_id.to_def_id(), sig.output());
|
||||
|
||||
// If both regions and types are empty, then this GAT isn't in the
|
||||
// return type, and we shouldn't try to do clause analysis
|
||||
|
@ -602,7 +602,6 @@ fn resolve_regions_with_wf_tys<'tcx>(
|
|||
/// the two vectors, `regions` and `types` (depending on their kind). For each
|
||||
/// parameter `Pi` also track the index `i`.
|
||||
struct GATSubstCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
gat: DefId,
|
||||
// Which region appears and which parameter index its subsituted for
|
||||
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
|
||||
|
@ -612,16 +611,11 @@ struct GATSubstCollector<'tcx> {
|
|||
|
||||
impl<'tcx> GATSubstCollector<'tcx> {
|
||||
fn visit<T: TypeFoldable<'tcx>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
gat: DefId,
|
||||
t: T,
|
||||
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
|
||||
let mut visitor = GATSubstCollector {
|
||||
tcx,
|
||||
gat,
|
||||
regions: FxHashSet::default(),
|
||||
types: FxHashSet::default(),
|
||||
};
|
||||
let mut visitor =
|
||||
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
||||
t.visit_with(&mut visitor);
|
||||
(visitor.regions, visitor.types)
|
||||
}
|
||||
|
@ -649,10 +643,6 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
|
|||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.tcx)
|
||||
}
|
||||
}
|
||||
|
||||
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
||||
|
@ -1198,7 +1188,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
// Ignore dependent defaults -- that is, where the default of one type
|
||||
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
||||
// be sure if it will error or not as user might always specify the other.
|
||||
if !ty.definitely_needs_subst(tcx) {
|
||||
if !ty.needs_subst() {
|
||||
fcx.register_wf_obligation(
|
||||
ty.into(),
|
||||
tcx.def_span(param.def_id),
|
||||
|
@ -1214,7 +1204,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
|
||||
// we should eagerly error.
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
if !default_ct.definitely_needs_subst(tcx) {
|
||||
if !default_ct.needs_subst() {
|
||||
fcx.register_wf_obligation(
|
||||
default_ct.into(),
|
||||
tcx.def_span(param.def_id),
|
||||
|
@ -1248,7 +1238,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
if is_our_default(param) {
|
||||
let default_ty = tcx.type_of(param.def_id);
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ty.definitely_needs_subst(tcx) {
|
||||
if !default_ty.needs_subst() {
|
||||
// ... then substitute it with the default.
|
||||
return default_ty.into();
|
||||
}
|
||||
|
@ -1261,7 +1251,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
if is_our_default(param) {
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ct.definitely_needs_subst(tcx) {
|
||||
if !default_ct.needs_subst() {
|
||||
// ... then substitute it with the default.
|
||||
return default_ct.into();
|
||||
}
|
||||
|
@ -1277,15 +1267,12 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
.predicates
|
||||
.iter()
|
||||
.flat_map(|&(pred, sp)| {
|
||||
struct CountParams<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
#[derive(Default)]
|
||||
struct CountParams {
|
||||
params: FxHashSet<u32>,
|
||||
}
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
||||
type BreakTy = ();
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.tcx)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::Param(param) = t.kind() {
|
||||
|
@ -1305,12 +1292,12 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||
c.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
let mut param_count = CountParams { tcx: fcx.tcx, params: FxHashSet::default() };
|
||||
let mut param_count = CountParams::default();
|
||||
let has_region = pred.visit_with(&mut param_count).is_break();
|
||||
let substituted_pred = pred.subst(tcx, substs);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.definitely_has_param_types_or_consts(tcx)
|
||||
if substituted_pred.has_param_types_or_consts()
|
||||
|| param_count.params.len() > 1
|
||||
|| has_region
|
||||
{
|
||||
|
@ -1698,7 +1685,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI
|
|||
for obligation in implied_obligations {
|
||||
let pred = obligation.predicate;
|
||||
// Match the existing behavior.
|
||||
if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
|
||||
if pred.is_global() && !pred.has_late_bound_regions() {
|
||||
let pred = fcx.normalize_associated_types_in(span, pred);
|
||||
let hir_node = fcx.tcx.hir().find(id);
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
|
||||
fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
|
||||
debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
|
||||
assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions(self.tcx()));
|
||||
assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
|
||||
self.typeck_results.node_types_mut().insert(hir_id, ty);
|
||||
}
|
||||
|
||||
|
@ -750,7 +750,7 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
|
|||
self.tcx
|
||||
}
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
|
||||
if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) {
|
||||
ty.super_fold_with(self)
|
||||
} else {
|
||||
ty
|
||||
|
|
|
@ -67,7 +67,6 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
|||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
opt_const_param_of: type_of::opt_const_param_of,
|
||||
default_anon_const_substs: type_of::default_anon_const_substs,
|
||||
type_of: type_of::type_of,
|
||||
item_bounds: item_bounds::item_bounds,
|
||||
explicit_item_bounds: item_bounds::explicit_item_bounds,
|
||||
|
@ -2277,7 +2276,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||
tcx,
|
||||
&mut predicates,
|
||||
trait_ref,
|
||||
&mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
|
||||
&mut cgp::parameters_for_impl(self_ty, trait_ref),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_hir::intravisit;
|
|||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{HirId, Node};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::symbol::Ident;
|
||||
|
@ -278,32 +278,6 @@ fn get_path_containing_arg_in_pat<'hir>(
|
|||
arg_path
|
||||
}
|
||||
|
||||
pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
if let Some(parent) = generics.parent {
|
||||
// This is the reason we bother with having optional anon const substs.
|
||||
//
|
||||
// In the future the substs of an anon const will depend on its parents predicates
|
||||
// at which point eagerly looking at them will cause a query cycle.
|
||||
//
|
||||
// So for now this is only an assurance that this approach won't cause cycle errors in
|
||||
// the future.
|
||||
let _cycle_check = tcx.predicates_of(parent);
|
||||
}
|
||||
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
// We only expect substs with the following type flags as default substs.
|
||||
//
|
||||
// Getting this wrong can lead to ICE and unsoundness, so we assert it here.
|
||||
for arg in substs.iter() {
|
||||
let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
|
||||
| ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE
|
||||
| ty::TypeFlags::HAS_ERROR;
|
||||
assert!(!arg.has_type_flags(!allowed_flags));
|
||||
}
|
||||
substs
|
||||
}
|
||||
|
||||
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
let def_id = def_id.expect_local();
|
||||
use rustc_hir::*;
|
||||
|
|
|
@ -27,13 +27,12 @@ impl From<ty::ParamConst> for Parameter {
|
|||
|
||||
/// Returns the set of parameters constrained by the impl header.
|
||||
pub fn parameters_for_impl<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_self_ty: Ty<'tcx>,
|
||||
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> FxHashSet<Parameter> {
|
||||
let vec = match impl_trait_ref {
|
||||
Some(tr) => parameters_for(tcx, &tr, false),
|
||||
None => parameters_for(tcx, &impl_self_ty, false),
|
||||
Some(tr) => parameters_for(&tr, false),
|
||||
None => parameters_for(&impl_self_ty, false),
|
||||
};
|
||||
vec.into_iter().collect()
|
||||
}
|
||||
|
@ -44,26 +43,20 @@ pub fn parameters_for_impl<'tcx>(
|
|||
/// of parameters whose values are needed in order to constrain `ty` - these
|
||||
/// differ, with the latter being a superset, in the presence of projections.
|
||||
pub fn parameters_for<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
t: &impl TypeFoldable<'tcx>,
|
||||
include_nonconstraining: bool,
|
||||
) -> Vec<Parameter> {
|
||||
let mut collector = ParameterCollector { tcx, parameters: vec![], include_nonconstraining };
|
||||
let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
|
||||
t.visit_with(&mut collector);
|
||||
collector.parameters
|
||||
}
|
||||
|
||||
struct ParameterCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
struct ParameterCollector {
|
||||
parameters: Vec<Parameter>,
|
||||
include_nonconstraining: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.tcx)
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *t.kind() {
|
||||
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
|
||||
|
@ -205,12 +198,12 @@ pub fn setup_constraining_predicates<'tcx>(
|
|||
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
|
||||
// Then the projection only applies if `T` is known, but it still
|
||||
// does not determine `U`.
|
||||
let inputs = parameters_for(tcx, &projection.projection_ty, true);
|
||||
let inputs = parameters_for(&projection.projection_ty, true);
|
||||
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
|
||||
if !relies_only_on_inputs {
|
||||
continue;
|
||||
}
|
||||
input_parameters.extend(parameters_for(tcx, &projection.ty, false));
|
||||
input_parameters.extend(parameters_for(&projection.ty, false));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ fn enforce_impl_params_are_constrained(
|
|||
let impl_predicates = tcx.predicates_of(impl_def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
|
||||
|
||||
let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
|
||||
let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
|
||||
cgp::identify_constrained_generic_params(
|
||||
tcx,
|
||||
impl_predicates,
|
||||
|
@ -134,7 +134,7 @@ fn enforce_impl_params_are_constrained(
|
|||
match item.kind {
|
||||
ty::AssocKind::Type => {
|
||||
if item.defaultness.has_value() {
|
||||
cgp::parameters_for(tcx, &tcx.type_of(def_id), true)
|
||||
cgp::parameters_for(&tcx.type_of(def_id), true)
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
|
|
|
@ -206,15 +206,15 @@ fn unconstrained_parent_impl_substs<'tcx>(
|
|||
continue;
|
||||
}
|
||||
|
||||
unconstrained_parameters.extend(cgp::parameters_for(tcx, &projection_ty, true));
|
||||
unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
|
||||
|
||||
for param in cgp::parameters_for(tcx, &projected_ty, false) {
|
||||
for param in cgp::parameters_for(&projected_ty, false) {
|
||||
if !unconstrained_parameters.contains(¶m) {
|
||||
constrained_params.insert(param.0);
|
||||
}
|
||||
}
|
||||
|
||||
unconstrained_parameters.extend(cgp::parameters_for(tcx, &projected_ty, true));
|
||||
unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ fn check_duplicate_params<'tcx>(
|
|||
parent_substs: &Vec<GenericArg<'tcx>>,
|
||||
span: Span,
|
||||
) {
|
||||
let mut base_params = cgp::parameters_for(tcx, parent_substs, true);
|
||||
let mut base_params = cgp::parameters_for(parent_substs, true);
|
||||
base_params.sort_by_key(|param| param.0);
|
||||
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
|
||||
let param = impl1_substs[duplicate.0 as usize];
|
||||
|
@ -376,7 +376,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
|||
match predicate.kind().skip_binder() {
|
||||
// Global predicates are either always true or always false, so we
|
||||
// are fine to specialize on.
|
||||
_ if predicate.is_global(tcx) => (),
|
||||
_ if predicate.is_global() => (),
|
||||
// We allow specializing on explicitly marked traits with no associated
|
||||
// items.
|
||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||
|
|
|
@ -114,18 +114,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
|
||||
) {
|
||||
// We must not look into the default substs of consts
|
||||
// as computing those depends on the results of `predicates_of`.
|
||||
//
|
||||
// Luckily the only types contained in default substs are type
|
||||
// parameters which don't matter here.
|
||||
//
|
||||
// FIXME(adt_const_params): Once complex const parameter types
|
||||
// are allowed, this might be incorrect. I think that we will still be
|
||||
// fine, as all outlives relations of the const param types should also
|
||||
// be part of the adt containing it, but we should still both update the
|
||||
// documentation and add some tests for this.
|
||||
for arg in field_ty.walk_ignoring_default_const_substs() {
|
||||
for arg in field_ty.walk() {
|
||||
let ty = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => ty,
|
||||
|
||||
|
@ -317,7 +306,7 @@ pub fn check_explicit_predicates<'tcx>(
|
|||
// 'b`.
|
||||
if let Some(self_ty) = ignored_self_ty {
|
||||
if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() {
|
||||
if ty.walk(tcx).any(|arg| arg == self_ty.into()) {
|
||||
if ty.walk().any(|arg| arg == self_ty.into()) {
|
||||
debug!("skipping self ty = {:?}", &ty);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -405,8 +405,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
|
||||
match &val.val {
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
let substs = uv.substs(self.tcx());
|
||||
self.add_constraints_from_invariant_substs(current, substs, variance);
|
||||
self.add_constraints_from_invariant_substs(current, uv.substs, variance);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue