From f4b606fd1703fb54bf75f064482312a67beb4a7b Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 13 Mar 2021 16:05:15 +0100 Subject: require a `tcx` for `TypeVisitor` --- src/tools/clippy/clippy_lints/src/redundant_clone.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/tools') diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 530b3396abe..2335d2248aa 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::{ visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, Mutability, }; -use rustc_middle::ty::{self, fold::TypeVisitor, Ty}; +use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt}; use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; @@ -576,7 +576,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { self.possible_borrower.add(borrowed.local, lhs); }, other => { - if ContainsRegion + if ContainsRegion(self.cx.tcx) .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty) .is_continue() { @@ -625,7 +625,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { .flat_map(HybridBitSet::iter) .collect(); - if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() { + if ContainsRegion(self.cx.tcx).visit_ty(self.body.local_decls[*dest].ty).is_break() { mutable_variables.push(*dest); } @@ -701,12 +701,15 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> { } } -struct ContainsRegion; +struct ContainsRegion<'tcx>(TyCtxt<'tcx>); -impl TypeVisitor<'_> for ContainsRegion { +impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> { type BreakTy = (); + fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { + self.0 + } - fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow { + fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { ControlFlow::BREAK } } -- cgit 1.4.1-3-g733a5 From bfaf13af4e5071b09248979e51c6614bf1353f52 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 16 Mar 2021 00:05:45 +0100 Subject: make unevaluated const substs optional --- compiler/rustc_codegen_cranelift/src/constant.rs | 10 ++--- compiler/rustc_infer/src/infer/combine.rs | 18 ++++----- .../rustc_infer/src/infer/error_reporting/mod.rs | 4 +- .../nice_region_error/static_impl_trait.rs | 6 ++- compiler/rustc_infer/src/infer/mod.rs | 10 ++--- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 4 +- compiler/rustc_infer/src/infer/resolve.rs | 4 +- compiler/rustc_lint/src/types.rs | 4 +- compiler/rustc_middle/src/mir/interpret/queries.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 ++ compiler/rustc_middle/src/ty/consts.rs | 3 +- compiler/rustc_middle/src/ty/consts/kind.rs | 38 +++++++++++++------ compiler/rustc_middle/src/ty/flags.rs | 3 +- compiler/rustc_middle/src/ty/fold.rs | 35 +++++++++++------- compiler/rustc_middle/src/ty/print/pretty.rs | 43 +++++++++++----------- compiler/rustc_middle/src/ty/relate.rs | 8 ++-- compiler/rustc_middle/src/ty/structural_impls.rs | 31 ++++++++++++---- compiler/rustc_middle/src/ty/walk.rs | 3 +- .../rustc_mir/src/borrow_check/type_check/mod.rs | 8 ++-- compiler/rustc_mir/src/interpret/operand.rs | 6 +-- compiler/rustc_mir/src/interpret/util.rs | 4 +- .../rustc_mir/src/monomorphize/polymorphize.rs | 16 ++++---- .../src/transform/check_consts/qualifs.rs | 2 +- compiler/rustc_mir/src/transform/const_prop.rs | 2 +- compiler/rustc_mir/src/transform/promote_consts.rs | 18 +++++---- compiler/rustc_mir/src/util/pretty.rs | 8 ++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 14 +++---- compiler/rustc_privacy/src/lib.rs | 4 +- compiler/rustc_trait_selection/src/opaque_types.rs | 4 +- .../src/traits/const_evaluatable.rs | 11 ++---- .../rustc_trait_selection/src/traits/fulfill.rs | 5 ++- .../src/traits/object_safety.rs | 4 +- .../src/traits/structural_match.rs | 4 +- compiler/rustc_trait_selection/src/traits/wf.rs | 9 +++-- compiler/rustc_traits/src/chalk/lowering.rs | 9 +++-- compiler/rustc_ty_utils/src/instance.rs | 5 ++- compiler/rustc_typeck/src/check/check.rs | 19 +++++----- compiler/rustc_typeck/src/check/op.rs | 4 +- compiler/rustc_typeck/src/check/wfcheck.rs | 4 +- compiler/rustc_typeck/src/collect.rs | 4 +- compiler/rustc_typeck/src/collect/type_of.rs | 6 ++- .../rustc_typeck/src/constrained_generic_params.rs | 4 +- src/librustdoc/clean/utils.rs | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 6 +-- .../clippy/clippy_lints/src/redundant_clone.rs | 4 +- src/tools/clippy/clippy_utils/src/consts.rs | 6 +-- 46 files changed, 234 insertions(+), 188 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c87309e2222..424a0d742d1 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -129,13 +129,13 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) - if fx.tcx.is_static(def.did) => + ConstKind::Unevaluated(uv) + if fx.tcx.is_static(uv.def.did) => { - assert!(substs.is_empty()); - assert!(promoted.is_none()); + assert!(uv.substs(fx.tcx).is_empty()); + assert!(uv.promoted.is_none()); - return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx); + return codegen_static_ref(fx, uv.def.did, fx.layout_of(const_.ty)).to_cvalue(fx); } ConstKind::Unevaluated(unevaluated) => { match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 01d84e287bc..4fb3d4bdfe1 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -742,10 +742,9 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) - if self.tcx().lazy_normalization() => - { - assert_eq!(promoted, None); + ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => { + assert_eq!(uv.promoted, None); + let substs = uv.substs(self.tcx()); let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -754,7 +753,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { )?; Ok(self.tcx().mk_const(ty::Const { ty: c.ty, - val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)), })) } _ => relate::super_relate_consts(self, c, c), @@ -976,10 +975,9 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) - if self.tcx().lazy_normalization() => - { - assert_eq!(promoted, None); + ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => { + assert_eq!(uv.promoted, None); + let substs = uv.substs(self.tcx()); let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -988,7 +986,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { )?; Ok(self.tcx().mk_const(ty::Const { ty: c.ty, - val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)), })) } _ => relate::super_relate_consts(self, c, c), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 14fdf03e06d..299dcf5f17a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1537,8 +1537,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index d3d55d89db6..81059fbcb10 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -479,8 +479,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) struct TraitObjectVisitor(pub(super) FxHashSet); impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for TraitObjectVisitor"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // The default anon const substs cannot include + // trait objects, so we don't have to bother looking. + None } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9013bea749a..155abf4ef83 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -679,7 +679,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { b: ty::Unevaluated<'tcx>, ) -> bool { let canonical = self.canonicalize_query( - ((a.def, a.substs), (b.def, b.substs)), + ((a.def, a.substs(self.tcx)), (b.def, b.substs(self.tcx))), &mut OriginalQueryValues::default(), ); debug!("canonical consts: {:?}", &canonical.value); @@ -1592,16 +1592,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>, + unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { let mut original_values = OriginalQueryValues::default(); - let canonical = self.canonicalize_query((param_env, substs), &mut original_values); + let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values); - let (param_env, substs) = canonical.value; + let (param_env, unevaluated) = canonical.value; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span) + self.tcx.const_eval_resolve(param_env, unevaluated, span) } /// If `typ` is a type variable of some kind, resolve it one level diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 8f1ebb116fd..c211d8e94a6 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -766,8 +766,8 @@ struct ScopeInstantiator<'me, 'tcx> { } impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_binder>( diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index e5ad44c7427..4b08c2eb9c1 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -127,8 +127,8 @@ impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> { type BreakTy = (Ty<'tcx>, Option); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.infcx.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.infcx.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1194d8edc09..5d255781639 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1160,8 +1160,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { type BreakTy = Ty<'tcx>; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.cx.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.cx.tcx) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index fa7c0670e8c..c63613ae3af 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> { ct: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { + match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 68de7f29193..737b1108f50 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -114,6 +114,10 @@ rustc_queries! { desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } } + query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> { + desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) } + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index c78151271c1..869b2ab9dbc 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,6 +1,5 @@ use crate::mir::interpret::ConstValue; use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::subst::InternalSubsts; use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{ParamEnv, ParamEnvAnd}; use rustc_errors::ErrorReported; @@ -100,7 +99,7 @@ impl<'tcx> Const<'tcx> { } _ => ty::ConstKind::Unevaluated(ty::Unevaluated { def: def.to_global(), - substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), + substs_: None, promoted: None, }), }; diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index f2db95d162b..ab2c57ac605 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -16,10 +16,23 @@ use super::ScalarInt; #[derive(Hash, HashStable)] pub struct Unevaluated<'tcx> { pub def: ty::WithOptConstParam, - pub substs: SubstsRef<'tcx>, + pub substs_: Option>, pub promoted: Option, } +impl<'tcx> Unevaluated<'tcx> { + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { + Unevaluated { def, substs_: Some(substs), promoted: None } + } + + pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> { + self.substs_.unwrap_or_else(|| { + debug_assert_eq!(self.promoted, None); + tcx.default_anon_const_substs(self.def.did) + }) + } +} + /// Represents a constant in Rust. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable)] @@ -109,7 +122,7 @@ impl<'tcx> ConstKind<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option, ErrorReported>> { - if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self { + if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` @@ -118,29 +131,32 @@ impl<'tcx> ConstKind<'tcx> { // Note that we erase regions *before* calling `with_reveal_all_normalized`, // so that we don't try to invoke this query with // any region variables. - let param_env_and_substs = tcx + let param_env_and = tcx .erase_regions(param_env) .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(substs)); + .and(tcx.erase_regions(unevaluated)); // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed // when the expression doesn't depend on any parameters. // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and_substs = if param_env_and_substs.needs_infer() { - tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did)) + let param_env_and = if param_env_and.needs_infer() { + tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { + def: unevaluated.def, + substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)), + promoted: unevaluated.promoted, + }) } else { - param_env_and_substs + param_env_and }; // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, substs) = param_env_and_substs.into_parts(); + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None) - { + match tcx.const_eval_resolve(param_env, unevaluated, None) { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 04df706d908..89cba4aab83 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -305,7 +305,8 @@ impl FlagComputation { } fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { - self.add_substs(ct.substs); + // TODO + self.add_substs(ct.substs_.unwrap()); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 40b3ffb8955..6e70e8ddaed 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -192,9 +192,11 @@ pub trait TypeVisitor<'tcx>: Sized { /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs /// are not yet supplied. /// - /// Visitors which do not look into these substs may leave this unimplemented, so be - /// careful when calling this method elsewhere. - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx>; + /// Visitors which do not look into these substs may return `None` here, in which case + /// `super_visit_with` completely skips the default substs. Incorrectly returning + /// `None` can very quickly lead to ICE or other critical bugs, so be careful and + /// try to return an actual `tcx` if at all possible. + fn tcx_for_anon_const_substs(&self) -> Option>; fn visit_binder>( &mut self, @@ -336,8 +338,8 @@ impl<'tcx> TyCtxt<'tcx> { { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_binder>( @@ -788,8 +790,9 @@ impl<'tcx> ValidateBoundVars<'tcx> { impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("default anon const substs can't contain bound vars"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // Anonymous constants do not contain bound vars in their substs by default. + None } fn visit_binder>( @@ -1006,8 +1009,9 @@ struct HasEscapingVarsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for HasEscpaingVarsVisitor"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // Anonymous constants do not contain bound vars in their substs by default. + None } fn visit_binder>( @@ -1080,8 +1084,13 @@ struct HasTypeFlagsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for HasTypeFlagsVisitor"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // TypeFlagsVisitor must not look into the default anon const substs + // as that would cause cycle errors, but we do care about them for + // some flags. + // + // We therefore have to be very careful here. + None } #[inline] @@ -1164,8 +1173,8 @@ impl LateBoundRegionsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_binder>( diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ef999285f53..13222363096 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -927,29 +927,28 @@ pub trait PrettyPrinter<'tcx>: } match ct.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { - def, - substs, - promoted: Some(promoted), - }) => { - p!(print_value_path(def.did, substs)); - p!(write("::{:?}", promoted)); - } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => { - match self.tcx().def_kind(def.did) { - DefKind::Static | DefKind::Const | DefKind::AssocConst => { - p!(print_value_path(def.did, substs)) - } - _ => { - if def.is_local() { - let span = self.tcx().def_span(def.did); - if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) + ty::ConstKind::Unevaluated(uv) => { + if let Some(promoted) = uv.promoted { + let substs = uv.substs_.unwrap(); + p!(print_value_path(uv.def.did, substs)); + p!(write("::{:?}", promoted)); + } else { + let tcx = self.tcx(); + match tcx.def_kind(uv.def.did) { + DefKind::Static | DefKind::Const | DefKind::AssocConst => { + p!(print_value_path(uv.def.did, uv.substs(tcx))) + } + _ => { + if uv.def.is_local() { + let span = tcx.def_span(uv.def.did); + if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) + } else { + print_underscore!() + } } else { print_underscore!() } - } else { - print_underscore!() } } } @@ -2025,8 +2024,8 @@ impl FmtPrinter<'_, 'tcx, F> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9c48f05617e..c978e1de38d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -579,7 +579,7 @@ pub fn super_relate_consts>( (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if tcx.features().const_evaluatable_checked => { - tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) + tcx.try_unify_abstract_consts(((au.def, au.substs(tcx)), (bu.def, bu.substs(tcx)))) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` @@ -591,13 +591,13 @@ pub fn super_relate_consts>( let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), - au.substs, - bu.substs, + au.substs(tcx), + bu.substs(tcx), )?; return Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, - substs, + substs_: Some(substs), promoted: au.promoted, }), ty: a.ty, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a46cac1e7f7..fe7d46240cb 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1046,13 +1046,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match self { ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - ty::ConstKind::Unevaluated(ty::Unevaluated { - def, - substs: substs.fold_with(folder), - promoted, - }) - } + ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) @@ -1064,7 +1058,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), - ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor), + ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) @@ -1082,3 +1076,24 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { ControlFlow::CONTINUE } } + +impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { + fn super_fold_with>(self, folder: &mut F) -> Self { + ty::Unevaluated { + def: self.def, + substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + promoted: self.promoted, + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + if let Some(tcx) = visitor.tcx_for_anon_const_substs() { + self.substs(tcx).visit_with(visitor) + } else if let Some(substs) = self.substs_ { + substs.visit_with(visitor) + } else { + debug!("ignoring default substs of `{:?}`", self.def); + ControlFlow::CONTINUE + } + } +} diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index c2fe5f1ef3f..c9fc97f0aaf 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -196,7 +196,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Error(_) => {} ty::ConstKind::Unevaluated(ct) => { - stack.extend(ct.substs.iter().rev()); + // TODO + stack.extend(ct.substs_.unwrap().iter().rev()); } } } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 999b25319bf..639bcb8fa94 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -377,8 +377,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { }, _ => None, }; - if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval { - if let Some(promoted) = promoted { + if let Some(uv) = maybe_uneval { + if let Some(promoted) = uv.promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, promoted: &Body<'tcx>, ty, @@ -413,8 +413,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( constant.literal.ty(), - def.did, - UserSubsts { substs, user_self_ty: None }, + uv.def.did, + UserSubsts { substs: uv.substs(self.tcx()), user_self_ty: None }, )), ) { span_mirbug!( diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 81f78621d14..403dc1b4793 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -555,9 +555,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match val.val { ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - let instance = self.resolve(def, substs)?; - Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) + ty::ConstKind::Unevaluated(uv) => { + let instance = self.resolve(uv.def, uv.substs(*self.tcx))?; + Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) } ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => { span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val) diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs index b7ab2e88b96..b9d6e002e2d 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_mir/src/interpret/util.rs @@ -21,8 +21,8 @@ where impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> { type BreakTy = FoundParam; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index dd7500e9e9d..b086053a0c1 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -283,8 +283,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } #[instrument(skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { @@ -298,7 +298,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted: Some(p)}) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => @@ -309,10 +309,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.visit_body(&promoted[p]); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) - if self.tcx.def_kind(def.did) == DefKind::AnonConst => + ty::ConstKind::Unevaluated(uv) + if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst => { - self.visit_child_body(def.did, substs); + self.visit_child_body(uv.def.did, uv.substs(self.tcx)); ControlFlow::CONTINUE } _ => c.super_visit_with(self), @@ -357,8 +357,8 @@ struct HasUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } #[instrument(skip(self))] diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs index ac8c748ea85..413a9638eb3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs @@ -247,7 +247,7 @@ where // Check the qualifs of the value of `const` items. if let Some(ct) = constant.literal.const_for_ty() { - if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val { + if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val { assert!(promoted.is_none()); // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def.did).is_none() { diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 4578f04c034..98581f76821 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -483,7 +483,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Promoteds must lint and not error as the user didn't ask for them ConstKind::Unevaluated(ty::Unevaluated { def: _, - substs: _, + substs_: _, promoted: Some(_), }) => true, // Out of backwards compatibility we cannot report hard errors in unused diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 822b422985c..14c9b3b0d47 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -859,13 +859,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { ty, val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, - substs: InternalSubsts::for_item(tcx, def.did, |param, _| { - if let ty::GenericParamDefKind::Lifetime = param.kind { - tcx.lifetimes.re_erased.into() - } else { - tcx.mk_param_from_def(param) - } - }), + substs_: Some(InternalSubsts::for_item( + tcx, + def.did, + |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }, + )), promoted: Some(promoted_id), }), }) diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 435fca4a11b..92591db668c 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -475,7 +475,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Unevaluated(uv) => format!( "Unevaluated({}, {:?}, {:?})", self.tcx.def_path_str(uv.def.did), - uv.substs, + uv.substs(self.tcx), uv.promoted ), ty::ConstKind::Value(val) => format!("Value({:?})", val), @@ -682,8 +682,10 @@ pub fn write_allocations<'tcx>( } struct CollectAllocIds(BTreeSet); impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for CollectAllocIds") + fn tcx_for_anon_const_substs(&self) -> Option> { + // `AllocId`s are only inside of `ConstKind::Value` which + // can't be part of the anon const default substs. + None } fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index f1d882e1ddd..9106f1d2342 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -693,11 +693,10 @@ impl<'tcx> Cx<'tcx> { // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); let lhs = ty::Const { - val: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: ty::WithOptConstParam::unknown(did), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new( + ty::WithOptConstParam::unknown(did), substs, - promoted: None, - }), + )), ty: var_ty, }; let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs))); @@ -889,11 +888,10 @@ impl<'tcx> Cx<'tcx> { debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: ty::WithOptConstParam::unknown(def_id), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new( + ty::WithOptConstParam::unknown(def_id), substs, - promoted: None, - }), + )), ty: self.typeck_results().node_type(expr.hir_id), }), user_ty, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 45d31068668..fb223d8fa75 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -179,8 +179,8 @@ where { type BreakTy = V::BreakTy; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.def_id_visitor.tcx() + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.def_id_visitor.tcx()) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 083a962ac7b..f89ca0fed03 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -558,8 +558,8 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_binder>( diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index b1a938836b7..2f1e7e9d509 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -155,11 +155,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve( - param_env, - ty::Unevaluated { def, substs, promoted: None }, - Some(span), - ); + let concrete = + infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span)); if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { @@ -217,9 +214,7 @@ impl AbstractConst<'tcx> { ct: &ty::Const<'tcx>, ) -> Result>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => { - AbstractConst::new(tcx, def, substs) - } + ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.def, uv.substs(tcx)), ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 4b94deff825..903912c3361 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -570,7 +570,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::ConstEquate(c1, c2) => { debug!(?c1, ?c2, "equating consts"); - if self.selcx.tcx().features().const_evaluatable_checked { + let tcx = self.selcx.tcx(); + if tcx.features().const_evaluatable_checked { // FIXME: we probably should only try to unify abstract constants // if the constants depend on generic parameters. // @@ -597,7 +598,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { Err(ErrorHandled::TooGeneric) => { stalled_on.extend( unevaluated - .substs + .substs(tcx) .iter() .filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b81ca52f9fd..01bad14c8fa 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -771,8 +771,8 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index fd7dc55ac84..ac8bab0cf36 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -130,8 +130,8 @@ impl Search<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { type BreakTy = NonStructuralMatchTy<'tcx>; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx() + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx()) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index afef784b4c6..e4457606132 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -435,13 +435,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { GenericArgKind::Const(constant) => { match constant.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert!(promoted.is_none()); + ty::ConstKind::Unevaluated(uv) => { + assert!(uv.promoted.is_none()); + let substs = uv.substs(self.tcx()); - let obligations = self.nominal_obligations(def.did, substs); + let obligations = self.nominal_obligations(uv.def.did, substs); self.out.extend(obligations); - let predicate = ty::PredicateKind::ConstEvaluatable(def, substs) + let predicate = ty::PredicateKind::ConstEvaluatable(uv.def, substs) .to_predicate(self.tcx()); let cause = self.cause(traits::MiscObligation); self.out.push(traits::Obligation::with_depth( diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index d07eeaedd82..1d4196e5747 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -854,8 +854,8 @@ impl<'tcx> BoundVarsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_binder>( @@ -1076,8 +1076,9 @@ impl PlaceholdersCollector { } impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for PlaceholdersCollector"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // Anon const substs do not contain placeholders by default. + None } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index b9fbb5da3e6..b00d2ab3561 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -54,8 +54,9 @@ impl<'tcx> BoundVarsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("default anon const substs can't be bound vars"); + fn tcx_for_anon_const_substs(&self) -> Option> { + // Anon const substs do not contain bound vars by default. + None } fn visit_binder>( &mut self, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 06fae26f7df..649574fe195 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -473,8 +473,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics); impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { type BreakTy = FoundParentLifetime; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.0 + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.0) } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { @@ -510,8 +510,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { type BreakTy = Ty<'tcx>; - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { @@ -1584,10 +1584,11 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t))) .filter(|(_, ty)| !matches!(ty.kind(), ty::Never)) { - struct VisitTypes(Vec); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - bug!("tcx_for_anon_const_substs called for VisitTypes"); + struct OpaqueTypeCollector(Vec); + impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector { + fn tcx_for_anon_const_substs(&self) -> Option> { + // Default anon const substs cannot contain opaque types. + None } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match *t.kind() { @@ -1599,7 +1600,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { } } } - let mut visitor = VisitTypes(vec![]); + let mut visitor = OpaqueTypeCollector(vec![]); ty.visit_with(&mut visitor); for def_id in visitor.0 { let ty_span = tcx.def_span(def_id); diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 3503d68e8f0..9b495fba197 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -1006,8 +1006,8 @@ fn suggest_constraining_param( struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec>); impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.0 + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.0) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { if let ty::Param(_) = ty.kind() { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 44caf348a98..0d121b9da87 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -831,8 +831,8 @@ fn check_where_clauses<'tcx, 'fcx>( } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index d5316352c54..a5a402bc26a 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -68,6 +68,7 @@ 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, @@ -2355,7 +2356,8 @@ fn const_evaluatable_predicates_of<'tcx>( assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx), + ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs(self.tcx)) + .to_predicate(self.tcx), span, )); } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 4048a54b58c..98f5f73b7be 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -7,7 +7,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::{GenericArgKind, InternalSubsts}; +use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; @@ -274,6 +274,10 @@ fn get_path_containing_arg_in_pat<'hir>( arg_path } +pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> { + InternalSubsts::identity_for_item(tcx, def_id) +} + pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let def_id = def_id.expect_local(); use rustc_hir::*; diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs index 140348ea4ec..9b6f0be47ca 100644 --- a/compiler/rustc_typeck/src/constrained_generic_params.rs +++ b/compiler/rustc_typeck/src/constrained_generic_params.rs @@ -60,8 +60,8 @@ struct ParameterCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> { - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.tcx + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index bdd5350aab2..bdfe3ffc13f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -287,7 +287,7 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) => { let mut s = if let Some(def) = def.as_local() { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did); print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id)) diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 3f9110295fc..2a85a67fa09 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -187,11 +187,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D let result = cx.tcx.const_eval_resolve( cx.param_env, - ty::Unevaluated { - def: ty::WithOptConstParam::unknown(def_id), - substs, - promoted: None, - }, + ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ); is_value_unfrozen_raw(cx, result, ty) diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 2335d2248aa..f5e43264a5c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -705,8 +705,8 @@ struct ContainsRegion<'tcx>(TyCtxt<'tcx>); impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { - self.0 + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.0) } fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 9ba1381da65..8bf31807d55 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -346,11 +346,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve( self.param_env, - ty::Unevaluated { - def: ty::WithOptConstParam::unknown(def_id), - substs, - promoted: None, - }, + ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ) .ok() -- cgit 1.4.1-3-g733a5 From cc47998e2877f13712a12b3814cc2bbf07fbae09 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 17 Jul 2021 16:43:23 +0200 Subject: add `tcx` to `fn walk` --- .../src/infer/error_reporting/need_type_info.rs | 2 +- compiler/rustc_infer/src/infer/outlives/verify.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 4 +-- compiler/rustc_middle/src/ty/outlives.rs | 2 +- compiler/rustc_middle/src/ty/walk.rs | 41 ++++++++++++---------- compiler/rustc_mir/src/monomorphize/collector.rs | 2 +- .../rustc_mir/src/transform/check_consts/check.rs | 2 +- .../src/transform/function_item_references.rs | 4 +-- .../src/thir/pattern/const_to_pat.rs | 2 +- .../rustc_trait_selection/src/traits/fulfill.rs | 5 +-- .../src/traits/object_safety.rs | 2 +- .../src/traits/select/confirmation.rs | 8 ++--- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 4 +-- compiler/rustc_typeck/src/astconv/mod.rs | 4 +-- compiler/rustc_typeck/src/check/check.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 2 +- .../rustc_typeck/src/outlives/implicit_infer.rs | 4 +-- src/tools/clippy/clippy_lints/src/escape.rs | 4 +-- .../clippy/clippy_lints/src/let_underscore.rs | 2 +- .../clippy_lints/src/loops/same_item_push.rs | 2 +- src/tools/clippy/clippy_lints/src/methods/mod.rs | 10 +++--- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../clippy_lints/src/self_named_constructors.rs | 4 +-- .../clippy/clippy_lints/src/unnecessary_sort_by.rs | 2 +- src/tools/clippy/clippy_lints/src/use_self.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +-- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 12 +++---- 29 files changed, 73 insertions(+), 67 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index c2025f3fe4d..e00003face9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> { fn node_ty_contains_target(&self, hir_id: HirId) -> Option> { self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| { - ty.walk().any(|inner| { + ty.walk(self.infcx.tcx).any(|inner| { inner == self.target || match (inner.unpack(), self.target.unpack()) { (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => { diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index f69212c599b..dba73251b4f 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -189,7 +189,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { visited: &mut SsoHashSet>, ) -> VerifyBound<'tcx> { let mut bounds = parent - .walk_shallow(visited) + .walk_shallow(self.tcx, visited) .filter_map(|child| match child.unpack() { GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)), GenericArgKind::Lifetime(lt) => { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index add0c0ff332..b4f11a8a044 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -152,8 +152,8 @@ declare_lint! { declare_lint_pass!(BoxPointers => [BOX_POINTERS]); impl BoxPointers { - fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) { - for leaf in ty.walk() { + fn check_heap_type<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { + for leaf in ty.walk(cx.tcx) { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if leaf_ty.is_box() { cx.struct_span_lint(BOX_POINTERS, span, |lint| { diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_middle/src/ty/outlives.rs index 86750d5c081..ef4ad998f10 100644 --- a/compiler/rustc_middle/src/ty/outlives.rs +++ b/compiler/rustc_middle/src/ty/outlives.rs @@ -194,7 +194,7 @@ fn compute_components_recursive( out: &mut SmallVec<[Component<'tcx>; 4]>, visited: &mut SsoHashSet>, ) { - for child in parent.walk_shallow(visited) { + for child in parent.walk_shallow(tcx, visited) { match child.unpack() { GenericArgKind::Type(ty) => { compute_components(tcx, ty, out, visited); diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index c9fc97f0aaf..3cab813f12a 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -1,8 +1,8 @@ //! An iterator over the type substructure. //! WARNING: this does not keep track of the region depth. -use crate::ty; use crate::ty::subst::{GenericArg, GenericArgKind}; +use crate::ty::{self, TyCtxt}; use rustc_data_structures::sso::SsoHashSet; use smallvec::{self, SmallVec}; @@ -11,6 +11,7 @@ use smallvec::{self, SmallVec}; type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>; pub struct TypeWalker<'tcx> { + tcx: TyCtxt<'tcx>, stack: TypeWalkerStack<'tcx>, last_subtree: usize, pub visited: SsoHashSet>, @@ -25,8 +26,8 @@ pub struct TypeWalker<'tcx> { /// It maintains a set of visited types and /// skips any types that are already there. impl<'tcx> TypeWalker<'tcx> { - pub fn new(root: GenericArg<'tcx>) -> Self { - Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() } + fn new(tcx: TyCtxt<'tcx>, root: GenericArg<'tcx>) -> Self { + Self { tcx, stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() } } /// Skips the subtree corresponding to the last type @@ -55,7 +56,7 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { let next = self.stack.pop()?; self.last_subtree = self.stack.len(); if self.visited.insert(next) { - push_inner(&mut self.stack, next); + push_inner(self.tcx, &mut self.stack, next); debug!("next: stack={:?}", self.stack); return Some(next); } @@ -74,8 +75,8 @@ impl GenericArg<'tcx> { /// Foo> => { Foo>, Bar, isize } /// [isize] => { [isize], isize } /// ``` - pub fn walk(self) -> TypeWalker<'tcx> { - TypeWalker::new(self) + pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { + TypeWalker::new(tcx, self) } /// Iterator that walks the immediate children of `self`. Hence @@ -87,10 +88,11 @@ impl GenericArg<'tcx> { /// and skips any types that are already there. pub fn walk_shallow( self, + tcx: TyCtxt<'tcx>, visited: &mut SsoHashSet>, ) -> impl Iterator> { let mut stack = SmallVec::new(); - push_inner(&mut stack, self); + push_inner(tcx, &mut stack, self); stack.retain(|a| visited.insert(*a)); stack.into_iter() } @@ -107,18 +109,22 @@ impl<'tcx> super::TyS<'tcx> { /// Foo> => { Foo>, Bar, isize } /// [isize] => { [isize], isize } /// ``` - pub fn walk(&'tcx self) -> TypeWalker<'tcx> { - TypeWalker::new(self.into()) + pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { + TypeWalker::new(tcx, self.into()) } } -// We push `GenericArg`s on the stack in reverse order so as to -// maintain a pre-order traversal. As of the time of this -// writing, the fact that the traversal is pre-order is not -// known to be significant to any code, but it seems like the -// natural order one would expect (basically, the order of the -// types as they are written). -fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) { +/// We push `GenericArg`s on the stack in reverse order so as to +/// maintain a pre-order traversal. As of the time of this +/// writing, the fact that the traversal is pre-order is not +/// known to be significant to any code, but it seems like the +/// natural order one would expect (basically, the order of the +/// types as they are written). +fn push_inner<'tcx>( + tcx: TyCtxt<'tcx>, + stack: &mut TypeWalkerStack<'tcx>, + parent: GenericArg<'tcx>, +) { match parent.unpack() { GenericArgKind::Type(parent_ty) => match *parent_ty.kind() { ty::Bool @@ -196,8 +202,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Error(_) => {} ty::ConstKind::Unevaluated(ct) => { - // TODO - stack.extend(ct.substs_.unwrap().iter().rev()); + stack.extend(ct.substs(tcx).iter().rev()); } } } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 95c4237f383..f03036267ac 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -573,7 +573,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { let type_length = instance .substs .iter() - .flat_map(|arg| arg.walk()) + .flat_map(|arg| arg.walk(tcx)) .filter(|arg| match arg.unpack() { GenericArgKind::Type(_) | GenericArgKind::Const(_) => true, GenericArgKind::Lifetime(_) => false, diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 09e908e6757..0361ddc915d 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -365,7 +365,7 @@ impl Checker<'mir, 'tcx> { fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) { let kind = self.body.local_kind(local); - for ty in ty.walk() { + for ty in ty.walk(self.tcx) { let ty = match ty.unpack() { GenericArgKind::Type(ty) => ty, diff --git a/compiler/rustc_mir/src/transform/function_item_references.rs b/compiler/rustc_mir/src/transform/function_item_references.rs index 26fe796cb91..ba2c91a9347 100644 --- a/compiler/rustc_mir/src/transform/function_item_references.rs +++ b/compiler/rustc_mir/src/transform/function_item_references.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> { // Handle calls to `transmute` if self.tcx.is_diagnostic_item(sym::transmute, def_id) { let arg_ty = args[0].ty(self.body, self.tcx); - for generic_inner_ty in arg_ty.walk() { + for generic_inner_ty in arg_ty.walk(self.tcx) { if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() { if let Some((fn_id, fn_substs)) = FunctionItemRefChecker::is_fn_ref(inner_ty) @@ -110,7 +110,7 @@ impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> { let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs(); for (arg_num, arg_def) in arg_defs.iter().enumerate() { // For all types reachable from the argument type in the fn sig - for generic_inner_ty in arg_def.walk() { + for generic_inner_ty in arg_def.walk(self.tcx) { if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() { // If the inner type matches the type bound by `Pointer` if TyS::same_type(inner_ty, bound_ty) { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 926bd830da0..bbb5de34d18 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -237,7 +237,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // code at the moment, because types like `for <'a> fn(&'a ())` do // not *yet* implement `PartialEq`. So for now we leave this here. has_impl - || ty.walk().any(|t| match t.unpack() { + || ty.walk(self.tcx()).any(|t| match t.unpack() { ty::subst::GenericArgKind::Lifetime(_) => false, ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(), ty::subst::GenericArgKind::Const(_) => false, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 903912c3361..110d83cbe28 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -767,14 +767,15 @@ fn substs_infer_vars<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> impl Iterator> { + let tcx = selcx.tcx(); selcx .infcx() .resolve_vars_if_possible(substs) .skip_binder() // ok because this check doesn't care about regions .iter() .filter(|arg| arg.has_infer_types_or_consts()) - .flat_map(|arg| { - let mut walker = arg.walk(); + .flat_map(move |arg| { + let mut walker = arg.walk(tcx); while let Some(c) = walker.next() { if !c.has_infer_types_or_consts() { walker.visited.remove(&c); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 01bad14c8fa..9511b41147d 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -278,7 +278,7 @@ fn predicate_references_self( (predicate, sp): (ty::Predicate<'tcx>, Span), ) -> Option { let self_ty = tcx.types.self_param; - let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); + let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk(tcx).any(|arg| arg == self_ty.into()); match predicate.kind().skip_binder() { ty::PredicateKind::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ba62ce1d531..c571a1d6284 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -947,7 +947,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut unsizing_params = GrowableBitSet::new_empty(); if tcx.features().relaxed_struct_unsize { - for arg in tail_field_ty.walk() { + for arg in tail_field_ty.walk(tcx) { if let Some(i) = maybe_unsizing_param_idx(arg) { unsizing_params.insert(i); } @@ -956,7 +956,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Ensure none of the other fields mention the parameters used // in unsizing. for field in prefix_fields { - for arg in tcx.type_of(field.did).walk() { + for arg in tcx.type_of(field.did).walk(tcx) { if let Some(i) = maybe_unsizing_param_idx(arg) { unsizing_params.remove(i); } @@ -968,7 +968,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } else { let mut found = false; - for arg in tail_field_ty.walk() { + for arg in tail_field_ty.walk(tcx) { if let Some(i) = maybe_unsizing_param_idx(arg) { unsizing_params.insert(i); found = true; @@ -984,7 +984,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // by putting it in a query; it would only need the `DefId` as it // looks at declared field types, not anything substituted. for field in prefix_fields { - for arg in tcx.type_of(field.did).walk() { + for arg in tcx.type_of(field.did).walk(tcx) { if let Some(i) = maybe_unsizing_param_idx(arg) { if unsizing_params.contains(i) { return Err(Unimplemented); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e4457606132..623215ec34e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -422,7 +422,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes all the predicates needed to validate that `ty` is WF into `out`. fn compute(&mut self, arg: GenericArg<'tcx>) { - let mut walker = arg.walk(); + let mut walker = arg.walk(self.tcx()); let param_env = self.param_env; let depth = self.recursion_depth; while let Some(arg) = walker.next() { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 8332e738411..1b0fff93a99 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -361,7 +361,7 @@ fn well_formed_types_in_env<'tcx>( // constituents are well-formed. NodeKind::InherentImpl => { let self_ty = tcx.type_of(def_id); - inputs.extend(self_ty.walk()); + inputs.extend(self_ty.walk(tcx)); } // In an fn, we assume that the arguments and all their constituents are @@ -370,7 +370,7 @@ fn well_formed_types_in_env<'tcx>( let fn_sig = tcx.fn_sig(def_id); let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig); - inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk())); + inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk(tcx))); } NodeKind::Other => (), diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 606fd2812ec..2879b7fcd91 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -394,7 +394,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().any(|arg| arg == self_param.into()) { + if default_ty.walk(tcx).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; @@ -1354,7 +1354,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().any(|arg| arg == dummy_self.into()); + pred.skip_binder().ty.walk(tcx).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. diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 649574fe195..3c9d5b4def4 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1482,7 +1482,7 @@ pub(super) fn check_type_params_are_used<'tcx>( return; } - for leaf in ty.walk() { + for leaf in ty.walk(tcx) { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if let ty::Param(param) = leaf_ty.kind() { debug!("found use of ty param {:?}", param); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index b624e07374e..9efb52a08b7 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -937,7 +937,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`, but the `FulfillmentError` references `T`. - if ty.walk().any(|arg| arg == predicate.self_ty().into()) { + if ty.walk(self.tcx).any(|arg| arg == predicate.self_ty().into()) { Some(i) } else { None diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index ccf0fb72738..985ee2169c9 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -114,7 +114,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { - for arg in field_ty.walk() { + for arg in field_ty.walk(tcx) { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -306,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().any(|arg| arg == self_ty.into()) { + if ty.walk(tcx).any(|arg| arg == self_ty.into()) { debug!("skipping self ty = {:?}", &ty); continue; } diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 8b0e9e6bc9b..685dbf26250 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -53,7 +53,7 @@ fn is_non_trait_box(ty: Ty<'_>) -> bool { struct EscapeDelegate<'a, 'tcx> { cx: &'a LateContext<'tcx>, set: HirIdSet, - trait_self_ty: Option>, + trait_self_ty: Option>, too_large_for_stack: u64, } @@ -171,7 +171,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { // skip if there is a `self` parameter binding to a type // that contains `Self` (i.e.: `self: Box`), see #4804 if let Some(trait_self_ty) = self.trait_self_ty { - if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(cmt.place.ty(), trait_self_ty) { + if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 8992d25932c..89146b4dd2c 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if let Some(init) = local.init; then { let init_ty = cx.typeck_results().expr_ty(init); - let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() { + let contains_sync_guard = init_ty.walk(cx.tcx).any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => { SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)) }, diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 0f6cd5de761..545498a1047 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -49,7 +49,7 @@ pub(super) fn check<'tcx>( if same_item_push_visitor.should_lint(); if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push; let vec_ty = cx.typeck_results().expr_ty(vec); - let ty = vec_ty.walk().nth(1).unwrap().expect_ty(); + let ty = vec_ty.walk(cx.tcx).nth(1).unwrap().expect_ty(); if cx .tcx .lang_items() diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 91606ed3b2b..9626cf79dc1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1987,10 +1987,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // walk the return type and check for Self (this does not check associated types) if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(ret_ty, self_adt) { + if contains_adt_constructor(cx.tcx, ret_ty, self_adt) { return; } - } else if contains_ty(ret_ty, self_ty) { + } else if contains_ty(cx.tcx, ret_ty, self_ty) { return; } @@ -2001,10 +2001,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(projection_predicate.ty, self_adt) { + if contains_adt_constructor(cx.tcx, projection_predicate.ty, self_adt) { return; } - } else if contains_ty(projection_predicate.ty, self_ty) { + } else if contains_ty(cx.tcx, projection_predicate.ty, self_ty) { return; } } @@ -2053,7 +2053,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.hir_id()); let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty(); - if !contains_ty(ret_ty, self_ty); + if !contains_ty(cx.tcx, ret_ty, self_ty); then { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index e153288aa58..681baed8c36 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -288,7 +288,7 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> { .fn_sig(def_id) .output() .skip_binder() - .walk() + .walk(self.cx.tcx) .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))); } diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 4472edecbed..4ba5e1a0f53 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -62,10 +62,10 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { // Ensure method is constructor-like if let Some(self_adt) = self_ty.ty_adt_def() { - if !contains_adt_constructor(ret_ty, self_adt) { + if !contains_adt_constructor(cx.tcx, ret_ty, self_adt) { return; } - } else if !contains_ty(ret_ty, self_ty) { + } else if !contains_ty(cx.tcx, ret_ty, self_ty) { return; } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs index 6fc5707a4ee..97b1b2dae3c 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -218,7 +218,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); - matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))) + matches!(ty.kind(), ty::Ref(..)) || ty.walk(cx.tcx).any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))) } impl LateLintPass<'_> for UnnecessarySortBy { diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index a3601cca2ef..9ae50e47ca4 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { // // See also https://github.com/rust-lang/rust-clippy/issues/2894. for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) { - if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) { + if trait_sem_ty.walk(cx.tcx).any(|inner| inner == self_ty.into()) { let mut visitor = SkipTyCollector::default(); visitor.visit_ty(impl_hir_ty); types_to_skip.extend(visitor.types_to_skip); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 32a73984674..98f3937ba3d 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1627,7 +1627,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option return Some("slice".into()), rustc_ty::Array(..) => return Some("array".into()), rustc_ty::Tuple(..) => return Some("tuple".into()), @@ -1635,7 +1635,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option, body: &'a Body<'tcx>, msrv: Option<&Ru } fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { - for arg in ty.walk() { + for arg in ty.walk(tcx) { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index a2221a0b283..3cd8ed5aa2c 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -10,7 +10,7 @@ use rustc_hir::{TyKind, Unsafety}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TypeFoldable, UintTy}; +use rustc_middle::ty::{self, TyCtxt, AdtDef, IntTy, Ty, TypeFoldable, UintTy}; use rustc_span::sym; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; @@ -36,8 +36,8 @@ pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } /// Walks into `ty` and returns `true` if any inner type is the same as `other_ty` -pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { - ty.walk().any(|inner| match inner.unpack() { +pub fn contains_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool { + ty.walk(tcx).any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }) @@ -45,8 +45,8 @@ pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { /// Walks into `ty` and returns `true` if any inner type is an instance of the given adt /// constructor. -pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool { - ty.walk().any(|inner| match inner.unpack() { +pub fn contains_adt_constructor<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, adt: &'tcx AdtDef) -> bool { + ty.walk(tcx).any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt), GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }) @@ -209,7 +209,7 @@ fn is_normalizable_helper<'tcx>( .iter() .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache)) }), - _ => ty.walk().all(|generic_arg| match generic_arg.unpack() { + _ => ty.walk(cx.tcx).all(|generic_arg| match generic_arg.unpack() { GenericArgKind::Type(inner_ty) if inner_ty != ty => { is_normalizable_helper(cx, param_env, inner_ty, cache) }, -- cgit 1.4.1-3-g733a5 From ab9108b70f25ecd9cce1ab756b82cb00de6c6927 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 17 Jul 2021 18:48:07 +0200 Subject: update `TypeFlags` to deal with missing ct substs --- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- .../src/infer/canonical/canonicalizer.rs | 2 +- compiler/rustc_infer/src/infer/freshen.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/noop_method_call.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 10 +- compiler/rustc_middle/src/ty/consts/kind.rs | 6 ++ compiler/rustc_middle/src/ty/erase_regions.rs | 4 +- compiler/rustc_middle/src/ty/flags.rs | 18 +++- compiler/rustc_middle/src/ty/fold.rs | 103 +++++++++++++++---- compiler/rustc_middle/src/ty/layout.rs | 6 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_middle/src/ty/structural_impls.rs | 4 + compiler/rustc_middle/src/ty/sty.rs | 20 ++-- compiler/rustc_middle/src/ty/subst.rs | 6 +- .../src/borrow_check/type_check/liveness/trace.rs | 2 +- compiler/rustc_mir/src/interpret/util.rs | 24 ++--- .../rustc_mir/src/monomorphize/polymorphize.rs | 8 +- compiler/rustc_mir/src/shim.rs | 24 ++++- compiler/rustc_mir/src/transform/const_prop.rs | 11 +- compiler/rustc_mir/src/transform/inline/cycle.rs | 2 +- compiler/rustc_mir/src/transform/mod.rs | 6 +- compiler/rustc_mir/src/transform/promote_consts.rs | 1 + compiler/rustc_mir_build/src/build/mod.rs | 10 +- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- compiler/rustc_symbol_mangling/src/v0.rs | 3 +- compiler/rustc_trait_selection/src/opaque_types.rs | 2 +- .../rustc_trait_selection/src/traits/coherence.rs | 2 +- .../src/traits/const_evaluatable.rs | 6 +- .../rustc_trait_selection/src/traits/fulfill.rs | 4 +- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- .../rustc_trait_selection/src/traits/select/mod.rs | 12 ++- compiler/rustc_type_ir/src/lib.rs | 112 ++++++++++++--------- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 8 +- compiler/rustc_typeck/src/check/wfcheck.rs | 12 +-- compiler/rustc_typeck/src/check/writeback.rs | 2 +- compiler/rustc_typeck/src/collect/type_of.rs | 11 +- .../src/impl_wf_check/min_specialization.rs | 2 +- .../clippy_lints/src/needless_pass_by_value.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 44 files changed, 305 insertions(+), 166 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 8375d4c7ca5..2e8a9604017 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -499,7 +499,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full - && !impl_self_ty.needs_subst() + && !impl_self_ty.needs_subst(cx.tcx) { Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 58ce31e0c4c..673d348a2a8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1398,7 +1398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), LocalRef::Operand(None) => { let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref())); - assert!(!dst_layout.ty.has_erasable_regions()); + assert!(!dst_layout.ty.has_erasable_regions(self.cx.tcx())); let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); self.codegen_transmute_into(bx, src, place); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3bbc481b610..e2edd448267 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -216,7 +216,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut allocate_local = |local| { let decl = &mir.local_decls[local]; let layout = bx.layout_of(fx.monomorphize(decl.ty)); - assert!(!layout.ty.has_erasable_regions()); + assert!(!layout.ty.has_erasable_regions(cx.tcx())); if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 448dd662348..c6e150d114c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -470,7 +470,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { { let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::NEEDS_INFER | - TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS` + TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_xxx_FREE_REGIONS` TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER } else { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 4af1bdf97a7..c40e409891b 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_infer() && !t.has_erasable_regions() { + if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) { return t; } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b4f11a8a044..8f848f54aad 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1656,7 +1656,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { ConstEquate(..) | TypeWellFormedFromEnv(..) => continue, }; - if predicate.is_global() { + if predicate.is_global(cx.tcx) { cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| { lint.build(&format!( "{} bound {} does not depend on any type \ diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 479cc00199f..908d847915f 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { _ => return, }; let substs = cx.typeck_results().node_substs(expr.hir_id); - if substs.needs_subst() { + if substs.needs_subst(cx.tcx) { // We can't resolve on types that require monomorphization, so we don't handle them if // we need to perfom substitution. return; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 00c2f0a0299..6a7758bedfb 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -242,6 +242,7 @@ pub struct Body<'tcx> { impl<'tcx> Body<'tcx> { pub fn new( + tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, basic_blocks: IndexVec>, source_scopes: IndexVec>, @@ -284,7 +285,7 @@ impl<'tcx> Body<'tcx> { predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), }; - body.is_polymorphic = body.has_param_types_or_consts(); + body.is_polymorphic = body.has_param_types_or_consts(tcx); body } @@ -293,7 +294,10 @@ impl<'tcx> Body<'tcx> { /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different /// crate. - pub fn new_cfg_only(basic_blocks: IndexVec>) -> Self { + pub fn new_cfg_only( + tcx: TyCtxt<'tcx>, + basic_blocks: IndexVec>, + ) -> Self { let mut body = Body { phase: MirPhase::Build, source: MirSource::item(DefId::local(CRATE_DEF_INDEX)), @@ -311,7 +315,7 @@ impl<'tcx> Body<'tcx> { predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), }; - body.is_polymorphic = body.has_param_types_or_consts(); + body.is_polymorphic = body.has_param_types_or_consts(tcx); body } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index ab2c57ac605..174c35dbc71 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -12,6 +12,12 @@ use rustc_target::abi::Size; use super::ScalarInt; /// An unevaluated, potentially generic, constant. +/// +/// If `substs_` is `None` it means that this anon const +/// still has its default substs. +/// +/// We check for all possible substs in `fn default_anon_const_substs`, +/// so refer to that check for more info. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable)] pub struct Unevaluated<'tcx> { diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 759d1a017aa..63eb55ed1a6 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -21,7 +21,9 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + if !value + .has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS) + { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 89cba4aab83..41c2447cfc5 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,6 +34,12 @@ impl FlagComputation { result.flags } + pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags { + let mut result = FlagComputation::new(); + result.add_unevaluated_const(uv); + result.flags + } + fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -91,7 +97,7 @@ impl FlagComputation { &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), &ty::Param(_) => { - self.add_flags(TypeFlags::HAS_TY_PARAM); + self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } @@ -292,7 +298,7 @@ impl FlagComputation { self.add_bound_var(debruijn); } ty::ConstKind::Param(_) => { - self.add_flags(TypeFlags::HAS_CT_PARAM); + self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Placeholder(_) => { @@ -305,8 +311,12 @@ impl FlagComputation { } fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { - // TODO - self.add_substs(ct.substs_.unwrap()); + if let Some(substs) = ct.substs_ { + self.add_substs(substs); + } else { + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); + self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS); + } self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 6e70e8ddaed..0c5e292e6eb 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -74,8 +74,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_vars_bound_at_or_above(ty::INNERMOST) } + fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool { + self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value() + == Some(FoundFlags) + } + fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) + self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value() + == Some(FoundFlags) } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) @@ -86,8 +92,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } - fn has_param_types_or_consts(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) + fn has_potential_param_types_or_consts(&self) -> bool { + self.has_type_flags( + TypeFlags::HAS_KNOWN_TY_PARAM + | TypeFlags::HAS_KNOWN_CT_PARAM + | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS, + ) + } + fn has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool { + self.definitely_has_type_flags( + tcx, + TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM, + ) } fn has_infer_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_INFER) @@ -108,13 +124,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { | TypeFlags::HAS_CT_PLACEHOLDER, ) } - fn needs_subst(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST) + fn potentially_needs_subst(&self) -> bool { + self.has_type_flags( + TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS, + ) + } + fn needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool { + self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST) } /// "Free" regions in this context means that it has any region /// that is not (a) erased or (b) late-bound. - fn has_free_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool { + self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS) } fn has_erased_regions(&self) -> bool { @@ -122,15 +143,25 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } /// True if there are any un-erased free regions. - fn has_erasable_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool { + self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS) + } + + /// Indicates whether this value definitely references only 'global' + /// generic parameters that are the same regardless of what fn we are + /// in. This is used for caching. + /// + /// Note that this function is pessimistic and may incorrectly return + /// `false`. + fn is_known_global(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES) } /// Indicates whether this value references only 'global' /// generic parameters that are the same regardless of what fn we are /// in. This is used for caching. - fn is_global(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) + fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool { + !self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES) } /// True if there are any late-bound regions @@ -217,6 +248,10 @@ pub trait TypeVisitor<'tcx>: Sized { c.super_visit_with(self) } + fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + uv.super_visit_with(self) + } + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { p.super_visit_with(self) } @@ -369,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { // We're only interested in types involving regions - if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { + if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { ty.super_visit_with(self) } else { ControlFlow::CONTINUE @@ -1078,23 +1113,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { struct FoundFlags; // FIXME: Optimize for checking for infer flags -struct HasTypeFlagsVisitor { +struct HasTypeFlagsVisitor<'tcx> { + tcx: Option>, flags: ty::TypeFlags, } -impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { +impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { type BreakTy = FoundFlags; fn tcx_for_anon_const_substs(&self) -> Option> { - // TypeFlagsVisitor must not look into the default anon const substs - // as that would cause cycle errors, but we do care about them for - // some flags. - // - // We therefore have to be very careful here. - None + self.tcx } #[inline] - fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { debug!( "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, @@ -1103,6 +1134,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { ); if t.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) + } else if self.tcx.is_some() + && t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) + && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) + { + t.super_visit_with(self) } else { ControlFlow::CONTINUE } @@ -1125,6 +1161,26 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) + } else if self.tcx.is_some() + && flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) + && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) + { + c.super_visit_with(self) + } else { + ControlFlow::CONTINUE + } + } + + fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + let flags = FlagComputation::for_unevaluated_const(uv); + debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else if self.tcx.is_some() + && flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) + && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) + { + uv.super_visit_with(self) } else { ControlFlow::CONTINUE } @@ -1138,6 +1194,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { ); if predicate.inner.flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) + } else if self.tcx.is_some() + && predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) + && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) + { + predicate.super_visit_with(self) } else { ControlFlow::CONTINUE } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8f90c7a8845..6761fbaf536 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1727,7 +1727,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Ignore layouts that are done with non-empty environments or // non-monomorphic layouts, as the user only wants to see the stuff // resulting from the final codegen session. - if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() { + if layout.ty.has_param_types_or_consts(self.tcx) + || !self.param_env.caller_bounds().is_empty() + { return; } @@ -1894,7 +1896,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); match tail.kind() { ty::Param(_) | ty::Projection(_) => { - debug_assert!(tail.has_param_types_or_consts()); + debug_assert!(tail.has_param_types_or_consts(tcx)); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) }) } _ => bug!( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 62e093581b8..eccc1ebd805 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1292,7 +1292,7 @@ impl<'tcx> ParamEnv<'tcx> { Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, Reveal::All => { - if value.is_global() { + if value.is_known_global() { ParamEnvAnd { param_env: self.without_caller_bounds(), value } } else { ParamEnvAnd { param_env: self, value } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 13222363096..5c3da507e14 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1201,7 +1201,9 @@ pub trait PrettyPrinter<'tcx>: // // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the // correct `ty::ParamEnv` to allow printing *all* constant values. - (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { + (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) + if !ty.has_potential_param_types_or_consts() => + { let contents = self.tcx().destructure_const( ty::ParamEnv::reveal_all() .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index fe7d46240cb..369dfaf32a0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1086,6 +1086,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { } } + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_unevaluated_const(*self) + } + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { if let Some(tcx) = visitor.tcx_for_anon_const_substs() { self.substs(tcx).visit_with(visitor) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8e0a2d4a28d..8b893b779c0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1565,26 +1565,26 @@ impl RegionKind { match *self { ty::ReVar(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; } ty::RePlaceholder(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } ty::ReEarlyBound(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_PARAM; + flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM; } ty::ReFree { .. } => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; } ty::ReEmpty(_) | ty::ReStatic => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; } ty::ReLateBound(..) => { flags = flags | TypeFlags::HAS_RE_LATE_BOUND; diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 84ec2e76c0b..2438d1a1602 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -486,7 +486,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_subst() { + if !t.potentially_needs_subst() { return t; } @@ -497,10 +497,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { } fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if !c.needs_subst() { - return c; - } - if let ty::ConstKind::Param(p) = c.val { self.const_for_param(p, c) } else { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs index e411f1dc108..566c11811e6 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs @@ -171,7 +171,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for (local, location) in drop_used { if !live_locals.contains(&local) { let local_ty = self.cx.body.local_decls[local].ty; - if local_ty.has_free_regions() { + if local_ty.has_free_regions(self.cx.typeck.tcx()) { self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); } } diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs index b9d6e002e2d..37c13c2d42a 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_mir/src/interpret/util.rs @@ -9,7 +9,7 @@ where T: TypeFoldable<'tcx>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.needs_subst() { + if !ty.potentially_needs_subst() { return Ok(()); } @@ -25,19 +25,8 @@ where Some(self.tcx) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { - if !c.needs_subst() { - return ControlFlow::CONTINUE; - } - - match c.val { - ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), - _ => c.super_visit_with(self), - } - } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if !ty.needs_subst() { + if !ty.potentially_needs_subst() { return ControlFlow::CONTINUE; } @@ -54,7 +43,7 @@ where let is_used = unused_params.contains(index).map_or(true, |unused| !unused); // Only recurse when generic parameters in fns, closures and generators // are used and require substitution. - match (is_used, subst.needs_subst()) { + match (is_used, subst.needs_subst(self.tcx)) { // Just in case there are closures or generators within this subst, // recurse. (true, true) => return subst.super_visit_with(self), @@ -77,6 +66,13 @@ where _ => ty.super_visit_with(self), } } + + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { + match c.val { + ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), + _ => c.super_visit_with(self), + } + } } let mut vis = UsedParamsNeedSubstVisitor { tcx }; diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index b086053a0c1..368ac70b552 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -288,7 +288,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } #[instrument(skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { - if !c.has_param_types_or_consts() { + if !c.has_potential_param_types_or_consts() { return ControlFlow::CONTINUE; } @@ -321,7 +321,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if !ty.has_param_types_or_consts() { + if !ty.has_potential_param_types_or_consts() { return ControlFlow::CONTINUE; } @@ -363,7 +363,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { #[instrument(skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { - if !c.has_param_types_or_consts() { + if !c.has_potential_param_types_or_consts() { return ControlFlow::CONTINUE; } @@ -381,7 +381,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { #[instrument(skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if !ty.has_param_types_or_consts() { + if !ty.has_potential_param_types_or_consts() { return ControlFlow::CONTINUE; } diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 8c3d828894c..8083ec95447 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -163,7 +163,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty)); let mut body = - new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); + new_body(tcx, source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); if ty.is_some() { // The first argument (index 0), but add 1 for the return value. @@ -202,6 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) } fn new_body<'tcx>( + tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, basic_blocks: IndexVec>, local_decls: IndexVec>, @@ -209,6 +210,7 @@ fn new_body<'tcx>( span: Span, ) -> Body<'tcx> { Body::new( + tcx, source, basic_blocks, IndexVec::from_elem_n( @@ -353,7 +355,14 @@ impl CloneShimBuilder<'tcx> { self.def_id, self.sig.inputs_and_output[0], )); - new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span) + new_body( + self.tcx, + source, + self.blocks, + self.local_decls, + self.sig.inputs().len(), + self.span, + ) } fn source_info(&self) -> SourceInfo { @@ -851,8 +860,14 @@ fn build_call_shim<'tcx>( block(&mut blocks, vec![], TerminatorKind::Resume, true); } - let mut body = - new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); + let mut body = new_body( + tcx, + MirSource::from_instance(instance), + blocks, + local_decls, + sig.inputs().len(), + span, + ); if let Abi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); @@ -917,6 +932,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { let source = MirSource::item(ctor_id); let body = new_body( + tcx, source, IndexVec::from_elem_n(start_block, 1), local_decls, diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 98581f76821..0d58625633f 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -120,7 +120,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { .predicates_of(def_id.to_def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|(p, _)| if p.is_global(tcx) { Some(*p) } else { None }); if traits::impossible_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), @@ -132,6 +132,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { trace!("ConstProp starting for {:?}", def_id); let dummy_body = &Body::new( + tcx, body.source, body.basic_blocks().clone(), body.source_scopes.clone(), @@ -468,7 +469,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Returns the value, if any, of evaluating `c`. fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option> { // FIXME we need to revisit this for #67176 - if c.needs_subst() { + if c.needs_subst(self.tcx) { return None; } @@ -488,9 +489,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }) => true, // Out of backwards compatibility we cannot report hard errors in unused // generic functions using associated constants of the generic parameters. - _ => c.literal.needs_subst(), + _ => c.literal.needs_subst(*tcx), }, - ConstantKind::Val(_, ty) => ty.needs_subst(), + ConstantKind::Val(_, ty) => ty.needs_subst(*tcx), }; if lint_only { // Out of backwards compatibility we cannot report hard errors in unused @@ -720,7 +721,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // FIXME we need to revisit this for #67176 - if rvalue.needs_subst() { + if rvalue.needs_subst(self.tcx) { return None; } diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs index c9eafafff57..46628b928de 100644 --- a/compiler/rustc_mir/src/transform/inline/cycle.rs +++ b/compiler/rustc_mir/src/transform/inline/cycle.rs @@ -89,7 +89,7 @@ crate fn mir_callgraph_reachable( // FIXME: A not fully substituted drop shim can cause ICEs if one attempts to // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this // needs some more analysis. - if callee.needs_subst() { + if callee.needs_subst(tcx) { continue; } } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index fa648a6dd49..d4c2456e9a4 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -400,7 +400,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) - } } - debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE"); + debug_assert!(!body.has_free_regions(tcx), "Free regions in MIR for CTFE"); body } @@ -594,7 +594,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal(); run_optimization_passes(tcx, &mut body); - debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR"); + debug_assert!(!body.has_free_regions(tcx), "Free regions in optimized MIR"); body } @@ -621,7 +621,7 @@ fn promoted_mir<'tcx>( run_post_borrowck_cleanup_passes(tcx, body); } - debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR"); + debug_assert!(!promoted.has_free_regions(tcx), "Free regions in promoted MIR"); tcx.arena.alloc(promoted) } diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 14c9b3b0d47..1b43670ba3a 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -992,6 +992,7 @@ pub fn promote_candidates<'tcx>( scope.parent_scope = None; let promoted = Body::new( + tcx, body.source, // `promoted` gets filled in below IndexVec::new(), IndexVec::from_elem_n(scope, 1), diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index bfebe860971..0a760a740dc 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -239,10 +239,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // The exception is `body.user_type_annotations`, which is used unmodified // by borrow checking. debug_assert!( - !(body.local_decls.has_free_regions() - || body.basic_blocks().has_free_regions() - || body.var_debug_info.has_free_regions() - || body.yield_ty().has_free_regions()), + !(body.local_decls.has_free_regions(tcx) + || body.basic_blocks().has_free_regions(tcx) + || body.var_debug_info.has_free_regions(tcx) + || body.yield_ty().has_free_regions(tcx)), "Unexpected free regions in MIR: {:?}", body, ); @@ -755,6 +755,7 @@ fn construct_error<'a, 'tcx>( cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); let mut body = Body::new( + tcx, MirSource::item(def.did.to_def_id()), cfg.basic_blocks, source_scopes, @@ -843,6 +844,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Body::new( + self.tcx, MirSource::item(self.def_id), self.cfg.basic_blocks, self.source_scopes, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 1b4e6b4e381..267e2d8808f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -109,7 +109,7 @@ fn get_symbol_hash<'tcx>( // Include the main item-type. Note that, in this case, the // assertions about `needs_subst` may not hold, but this item-type // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); + assert!(!item_type.has_erasable_regions(tcx)); hcx.while_hashing_spans(false, |hcx| { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { item_type.hash_stable(hcx, &mut hasher); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c4c1ec8ce4e..3ac9d1e5745 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -277,7 +277,8 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { // Encode impl generic params if the substitutions contain parameters (implying // polymorphization is enabled) and this isn't an inherent impl. - if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) { + if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts(self.tcx)) + { self = self.path_generic_args( |this| { this.path_append_ns( diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index f89ca0fed03..b743c809ca2 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -583,7 +583,7 @@ where fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { // We're only interested in types involving regions - if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { + if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { return ControlFlow::CONTINUE; } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9bb4af16a8f..6ab079ad404 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -391,7 +391,7 @@ fn orphan_check_trait_ref<'tcx>( ) -> Result<(), OrphanCheckErr<'tcx>> { debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate); - if trait_ref.needs_infer() && trait_ref.needs_subst() { + if trait_ref.needs_infer() && trait_ref.needs_subst(tcx) { bug!( "can't orphan check a trait ref with both params and inference variables {:?}", trait_ref diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 2f1e7e9d509..2cc74ca2abb 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -91,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( let leaf = leaf.subst(tcx, ct.substs); if leaf.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; - } else if leaf.has_param_types_or_consts() { + } else if leaf.has_param_types_or_consts(tcx) { failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam); } @@ -101,7 +101,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( let ty = ty.subst(tcx, ct.substs); if ty.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; - } else if ty.has_param_types_or_consts() { + } else if ty.has_param_types_or_consts(tcx) { failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam); } @@ -158,7 +158,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( let concrete = infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span)); - if concrete.is_ok() && substs.has_param_types_or_consts() { + if concrete.is_ok() && substs.has_param_types_or_consts(infcx.tcx) { match infcx.tcx.def_kind(def.did) { DefKind::AnonConst => { let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 110d83cbe28..edf2274ab54 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { stalled_on: &mut Vec>, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let infcx = self.selcx.infcx(); - if obligation.predicate.is_global() { + if obligation.predicate.is_known_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. // @@ -728,7 +728,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let tcx = self.selcx.tcx(); - if obligation.predicate.is_global() { + if obligation.predicate.is_global(tcx) { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. // diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 477d29f1a4f..43ee1c3304a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -450,7 +450,7 @@ fn subst_and_check_impossible_predicates<'tcx>( debug!("subst_and_check_impossible_predicates(key={:?})", key); let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates; - predicates.retain(|predicate| !predicate.needs_subst()); + predicates.retain(|predicate| !predicate.needs_subst(tcx)); let result = impossible_predicates(tcx, predicates); debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c150b222266..1c4e7e6c589 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }, ty::PredicateKind::TypeOutlives(pred) => { - if pred.0.is_global() { + if pred.0.is_known_global() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) @@ -692,8 +692,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligation, "evaluate_trait_predicate_recursively"); if !self.intercrate - && obligation.is_global() - && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst()) + && obligation.is_global(self.tcx()) + && obligation + .param_env + .caller_bounds() + .iter() + .all(|bound| bound.needs_subst(self.tcx())) { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear @@ -1452,7 +1456,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. let is_global = - |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions(); + |cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // and `DiscriminantKindCandidate` to anything else. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 2d102127dd9..c405bbe2d1f 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -19,94 +19,116 @@ bitflags! { // Does this have parameters? Used to determine whether substitution is // required. /// Does this have `Param`? - const HAS_TY_PARAM = 1 << 0; + const HAS_KNOWN_TY_PARAM = 1 << 0; /// Does this have `ReEarlyBound`? - const HAS_RE_PARAM = 1 << 1; + const HAS_KNOWN_RE_PARAM = 1 << 1; /// Does this have `ConstKind::Param`? - const HAS_CT_PARAM = 1 << 2; + const HAS_KNOWN_CT_PARAM = 1 << 2; - const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits; + const KNOWN_NEEDS_SUBST = TypeFlags::HAS_KNOWN_TY_PARAM.bits + | TypeFlags::HAS_KNOWN_RE_PARAM.bits + | TypeFlags::HAS_KNOWN_CT_PARAM.bits; /// Does this have `Infer`? - const HAS_TY_INFER = 1 << 3; + const HAS_TY_INFER = 1 << 3; /// Does this have `ReVar`? - const HAS_RE_INFER = 1 << 4; + const HAS_RE_INFER = 1 << 4; /// Does this have `ConstKind::Infer`? - const HAS_CT_INFER = 1 << 5; + const HAS_CT_INFER = 1 << 5; /// Does this have inference variables? Used to determine whether /// inference is required. - const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits - | TypeFlags::HAS_CT_INFER.bits; + const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits; /// Does this have `Placeholder`? - const HAS_TY_PLACEHOLDER = 1 << 6; + const HAS_TY_PLACEHOLDER = 1 << 6; /// Does this have `RePlaceholder`? - const HAS_RE_PLACEHOLDER = 1 << 7; + const HAS_RE_PLACEHOLDER = 1 << 7; /// Does this have `ConstKind::Placeholder`? - const HAS_CT_PLACEHOLDER = 1 << 8; + const HAS_CT_PLACEHOLDER = 1 << 8; /// `true` if there are "names" of regions and so forth /// that are local to a particular fn/inferctxt - const HAS_FREE_LOCAL_REGIONS = 1 << 9; + const HAS_KNOWN_FREE_LOCAL_REGIONS = 1 << 9; /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits - | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_CT_INFER.bits - | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits - // We consider 'freshened' types and constants - // to depend on a particular fn. - // The freshening process throws away information, - // which can make things unsuitable for use in a global - // cache. Note that there is no 'fresh lifetime' flag - - // freshening replaces all lifetimes with `ReErased`, - // which is different from how types/const are freshened. - | TypeFlags::HAS_TY_FRESH.bits - | TypeFlags::HAS_CT_FRESH.bits - | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; + const HAS_KNOWN_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_TY_PARAM.bits + | TypeFlags::HAS_KNOWN_CT_PARAM.bits + | TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_CT_INFER.bits + | TypeFlags::HAS_TY_PLACEHOLDER.bits + | TypeFlags::HAS_CT_PLACEHOLDER.bits + // We consider 'freshened' types and constants + // to depend on a particular fn. + // The freshening process throws away information, + // which can make things unsuitable for use in a global + // cache. Note that there is no 'fresh lifetime' flag - + // freshening replaces all lifetimes with `ReErased`, + // which is different from how types/const are freshened. + | TypeFlags::HAS_TY_FRESH.bits + | TypeFlags::HAS_CT_FRESH.bits + | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits; + + const HAS_POTENTIAL_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES.bits + | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits; /// Does this have `Projection`? - const HAS_TY_PROJECTION = 1 << 10; + const HAS_TY_PROJECTION = 1 << 10; /// Does this have `Opaque`? - const HAS_TY_OPAQUE = 1 << 11; + const HAS_TY_OPAQUE = 1 << 11; /// Does this have `ConstKind::Unevaluated`? - const HAS_CT_PROJECTION = 1 << 12; + const HAS_CT_PROJECTION = 1 << 12; /// Could this type be normalized further? - const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits - | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_CT_PROJECTION.bits; + const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits + | TypeFlags::HAS_TY_OPAQUE.bits + | TypeFlags::HAS_CT_PROJECTION.bits; /// Is an error type/const reachable? - const HAS_ERROR = 1 << 13; + const HAS_ERROR = 1 << 13; /// Does this have any region that "appears free" in the type? /// Basically anything but `ReLateBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 14; + const HAS_KNOWN_FREE_REGIONS = 1 << 14; + + const HAS_POTENTIAL_FREE_REGIONS = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits + | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits; /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 15; + const HAS_RE_LATE_BOUND = 1 << 15; /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 16; + const HAS_RE_ERASED = 1 << 16; /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? - const STILL_FURTHER_SPECIALIZABLE = 1 << 17; + /// + /// Note that this flag being set is not a guarantee, as it is also + /// set if there are any anon consts with unknown default substs. + const STILL_FURTHER_SPECIALIZABLE = 1 << 17; /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 18; + const HAS_TY_FRESH = 1 << 18; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 19; + const HAS_CT_FRESH = 1 << 19; + + /// Does this value have unknown default anon const substs. + /// + /// For more details refer to... + /// FIXME(@lcnr): ask me for now, still have to write all of this. + const HAS_UNKNOWN_DEFAULT_CONST_SUBSTS = 1 << 20; + /// Flags which can be influenced by default anon const substs. + const MAY_NEED_DEFAULT_CONST_SUBSTS = TypeFlags::HAS_KNOWN_RE_PARAM.bits + | TypeFlags::HAS_KNOWN_TY_PARAM.bits + | TypeFlags::HAS_KNOWN_CT_PARAM.bits + | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits + | TypeFlags::HAS_KNOWN_FREE_REGIONS.bits; + } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2879b7fcd91..bbfceeeff48 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2204,7 +2204,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.needs_subst() { + if forbid_generic && normalized_ty.needs_subst(tcx) { let mut err = tcx.sess.struct_span_err( path.span, "generic `Self` types are currently not permitted in anonymous constants", diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 15fa696b6c4..25d1c8706e8 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -239,7 +239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 }, @@ -481,7 +481,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); @@ -526,11 +526,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: T) -> bool + fn can_contain_user_lifetime_bounds(&self, t: T) -> bool where T: TypeFoldable<'tcx>, { - t.has_free_regions() || t.has_projections() || t.has_infer_types() + t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types() } pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 0d121b9da87..057a15a4358 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -746,7 +746,7 @@ fn check_where_clauses<'tcx, 'fcx>( // Ignore dependent defaults -- that is, where the default of one type // parameter includes another (e.g., ``). In those cases, we can't // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + if !ty.needs_subst(tcx) { fcx.register_wf_obligation( ty.into(), tcx.def_span(param.def_id), @@ -762,7 +762,7 @@ fn check_where_clauses<'tcx, 'fcx>( // for `struct Foo` // we should eagerly error. let default_ct = tcx.const_param_default(param.def_id); - if !default_ct.needs_subst() { + if !default_ct.needs_subst(tcx) { fcx.register_wf_obligation( default_ct.into(), tcx.def_span(param.def_id), @@ -796,7 +796,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.needs_subst() { + if !default_ty.needs_subst(tcx) { // ... then substitute it with the default. return default_ty.into(); } @@ -809,7 +809,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.needs_subst() { + if !default_ct.needs_subst(tcx) { // ... then substitute it with the default. return default_ct.into(); } @@ -858,7 +858,7 @@ fn check_where_clauses<'tcx, 'fcx>( 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.has_param_types_or_consts() + if substituted_pred.has_param_types_or_consts(tcx) || param_count.params.len() > 1 || has_region { @@ -1380,7 +1380,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { for obligation in implied_obligations { let pred = obligation.predicate; // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_regions() { + if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() { let pred = fcx.normalize_associated_types_in(span, pred); let obligation = traits::Obligation::new( traits::ObligationCause::new(span, id, traits::TrivialBound), diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 2e59defdb7b..c57ec9ef78f 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -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()); + assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions(self.tcx())); self.typeck_results.node_types_mut().insert(hir_id, ty); } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 98f5f73b7be..9b10874b8bc 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -275,7 +275,16 @@ fn get_path_containing_arg_in_pat<'hir>( } pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> { - InternalSubsts::identity_for_item(tcx, def_id) + 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().flat_map(|s| s.walk(tcx)) { + let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS + | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE; + assert!(!arg.has_type_flags(!allowed_flags)); + } + substs } pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 2d71c87bee7..d3e4be128a8 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -363,7 +363,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() => (), + _ if predicate.is_global(tcx) => (), // We allow specializing on explicitly marked traits with no associated // items. ty::PredicateKind::Trait(ty::TraitPredicate { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 5e559991c16..90b2aa16896 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let fn_def_id = cx.tcx.hir().local_def_id(hir_id); let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter()) - .filter(|p| !p.is_global()) + .filter(|p| !p.is_global(cx.tcx)) .filter_map(|obligation| { // Note that we do not want to deal with qualified predicates here. match obligation.predicate.kind().no_bound_vars() { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 98f3937ba3d..ddff1686ba2 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1581,7 +1581,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .predicates_of(did) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None }); traits::impossible_predicates( cx.tcx, traits::elaborate_predicates(cx.tcx, predicates) -- cgit 1.4.1-3-g733a5