Skip to content

'improve' type traversal #132046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
@@ -521,7 +521,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// C-variadic fns also have a `VaList` input that's not listed in the signature
// (as it's created inside the body itself, not passed in from outside).
if let DefiningTy::FnDef(def_id, _) = defining_ty {
if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
if self.infcx.tcx.fn_sig(def_id).extract(ty::Binder::c_variadic) {
let va_list_did = self.infcx.tcx.require_lang_item(
LangItem::VaList,
Some(self.infcx.tcx.def_span(self.mir_def)),
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
@@ -433,7 +433,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
None
};

let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
let extra_args = &args[fn_sig.inputs().extract(|inputs| inputs.len())..];
let extra_args = fx.tcx.mk_type_list_from_iter(
extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))),
);
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
@@ -202,7 +202,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {

if !is_closure
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().abi() != abi::Abi::Rust
&& fn_sig.extract(ty::Binder::abi) != abi::Abi::Rust
{
struct_span_code_err!(
tcx.dcx(),
@@ -245,7 +245,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
sym::target_feature => {
if !tcx.is_closure_like(did.to_def_id())
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().safety() == hir::Safety::Safe
&& fn_sig.extract(ty::Binder::safety) == hir::Safety::Safe
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
@@ -869,7 +869,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let sig = callee.layout.ty.fn_sig(bx.tcx());
let abi = sig.abi();

let extra_args = &args[sig.inputs().skip_binder().len()..];
let extra_args = &args[sig.inputs().extract(<[_]>::len)..];
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
let op_ty = op_arg.node.ty(self.mir, bx.tcx());
self.monomorphize(op_ty)
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::Symbol;
use {rustc_attr as attr, rustc_hir as hir};

@@ -77,7 +77,7 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if cfg!(debug_assertions) && stab.promotable {
let sig = tcx.fn_sig(def_id);
assert_eq!(
sig.skip_binder().safety(),
sig.extract(ty::Binder::safety),
hir::Safety::Safe,
"don't mark const unsafe fns as promotable",
// https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -650,7 +650,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
for &assoc_item in assoc_items.in_definition_order() {
match assoc_item.kind {
ty::AssocKind::Fn => {
let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
let abi = tcx.fn_sig(assoc_item.def_id).extract(ty::Binder::abi);
forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
}
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
@@ -1377,8 +1377,8 @@ fn compare_number_of_method_arguments<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len();
let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len();
let trait_number_args = trait_m_fty.skip_binder().inputs().extract(<[_]>::len);
let impl_number_args = impl_m_fty.skip_binder().inputs().extract(<[_]>::len);

if trait_number_args != impl_number_args {
let trait_span = trait_m
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ fn equate_intrinsic_type<'tcx>(
/// Returns the unsafety of the given intrinsic.
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
tcx.fn_sig(intrinsic_id).skip_binder().safety()
tcx.fn_sig(intrinsic_id).extract(ty::Binder::safety)
} else {
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
true => hir::Safety::Safe,
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -250,7 +250,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
hir::ItemKind::Impl(impl_) => {
let header = tcx.impl_trait_header(def_id);
let is_auto = header
.is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
.is_some_and(|header| tcx.trait_is_auto(header.trait_ref.extract(|tr| tr.def_id)));

crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
let mut res = Ok(());
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
@@ -296,7 +296,7 @@ fn orphan_check<'tcx>(
debug!(trait_ref = ?trait_ref.skip_binder());

// If the *trait* is local to the crate, ok.
if let Some(def_id) = trait_ref.skip_binder().def_id.as_local() {
if let Some(def_id) = trait_ref.extract(|tr| tr.def_id).as_local() {
debug!("trait {def_id:?} is local to current crate");
return Ok(());
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/delegation.rs
Original file line number Diff line number Diff line change
@@ -492,7 +492,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap();
let caller_sig = tcx.fn_sig(sig_id);
if let Err(err) = check_constraints(tcx, def_id, sig_id) {
let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
let sig_len = caller_sig.instantiate_identity().extract(|sig| sig.inputs().len()) + 1;
let err_type = Ty::new_error(tcx, err);
return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
}
Original file line number Diff line number Diff line change
@@ -94,7 +94,7 @@ pub(super) fn check_min_specialization(

fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> {
let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id);
let trait_def = tcx.trait_def(trait_ref.extract(|tr| tr.def_id));

let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?;

4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ pub(super) fn infer_predicates(
// items.
let item_predicates_len: usize = global_inferred_outlives
.get(&item_did.to_def_id())
.map_or(0, |p| p.as_ref().skip_binder().len());
.map_or(0, |p| p.extract_ref(|p| p.len()));
if item_required_predicates.len() > item_predicates_len {
predicates_added = true;
global_inferred_outlives
@@ -181,7 +181,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
let args = ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().args;
check_explicit_predicates(
tcx,
ex_trait_ref.skip_binder().def_id,
ex_trait_ref.extract(|tr| tr.def_id),
args,
required_predicates,
explicit_map,
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
@@ -688,7 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// expect.
if expected_sig.sig.c_variadic() != decl.c_variadic {
return self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind);
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
} else if expected_sig.sig.inputs().extract(<[_]>::len) != decl.inputs.len() {
return self.sig_of_closure_with_mismatched_number_of_arguments(
expr_def_id,
decl,
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
@@ -1009,7 +1009,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match method.kind {
ty::AssocKind::Fn => {
method.fn_has_self_parameter
&& self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len()
&& self.tcx.fn_sig(method.def_id).skip_binder().inputs().extract(<[_]>::len)
== 1
}
_ => false,
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -745,7 +745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// ```
//
// to work in stable even if the Sized bound on `drop` is relaxed.
for i in 0..fn_sig.inputs().skip_binder().len() {
for i in 0..fn_sig.inputs().extract(<[_]>::len) {
// We just want to check sizedness, so instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
@@ -2330,7 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !self.can_eq(self.param_env, ret_ty, adt_ty) {
return None;
}
let input_len = fn_sig.inputs().skip_binder().len();
let input_len = fn_sig.inputs().extract(<[_]>::len);
let order = !item.name.as_str().starts_with("new");
Some((order, item.name, input_len))
})
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/mod.rs
Original file line number Diff line number Diff line change
@@ -149,7 +149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
.map(|pick| {
let sig = self.tcx.fn_sig(pick.item.def_id);
sig.skip_binder().inputs().skip_binder().len().saturating_sub(1)
sig.skip_binder().inputs().extract(<[_]>::len).saturating_sub(1)
})
.unwrap_or(0);

2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -1987,7 +1987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// the impl, if local to crate (item may be defaulted), else nothing.
let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
self.associated_value(impl_trait_ref.skip_binder().def_id, item_name)
self.associated_value(impl_trait_ref.extract(|tr| tr.def_id), item_name)
}) else {
continue;
};
5 changes: 1 addition & 4 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
@@ -387,10 +387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let num_args = args
.as_coroutine_closure()
.coroutine_closure_sig()
.skip_binder()
.tupled_inputs_ty
.tuple_fields()
.len();
.extract(|sig| sig.tupled_inputs_ty.tuple_fields().len());
let typeck_results = self.typeck_results.borrow();

let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter(
17 changes: 11 additions & 6 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
@@ -15,8 +15,10 @@ use rustc_index::{Idx, IndexVec};
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::traverse::AlwaysTraversable;
use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_type_ir::traverse::OptTryFoldWith;
use tracing::{debug, instrument};

use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value};
@@ -60,7 +62,7 @@ impl<'tcx> InferCtxt<'tcx> {
fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
T: OptTryFoldWith<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
@@ -107,7 +109,7 @@ impl<'tcx> InferCtxt<'tcx> {
fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
) -> Result<QueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
T: OptTryFoldWith<TyCtxt<'tcx>>,
{
let tcx = self.tcx;

@@ -243,7 +245,7 @@ impl<'tcx> InferCtxt<'tcx> {
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> InferResult<'tcx, R>
where
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
R: OptTryFoldWith<TyCtxt<'tcx>>,
{
let InferOk { value: result_args, mut obligations } = self
.query_response_instantiation_guess(
@@ -326,8 +328,11 @@ impl<'tcx> InferCtxt<'tcx> {
.map(|p_c| instantiate_value(self.tcx, &result_args, p_c.clone())),
);

let user_result: R =
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
let user_result: R = query_response
.instantiate_projected(self.tcx, &result_args, |q_r| {
AlwaysTraversable(q_r.value.clone())
})
.0;

Ok(InferOk { value: user_result, obligations })
}
@@ -396,7 +401,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
where
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
R: OptTryFoldWith<TyCtxt<'tcx>>,
{
// For each new universe created in the query result that did
// not appear in the original query, create a local
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -171,7 +171,7 @@ impl<'tcx, O> Obligation<'tcx, O> {

impl<'tcx> PolyTraitObligation<'tcx> {
pub fn polarity(&self) -> ty::PredicatePolarity {
self.predicate.skip_binder().polarity
self.predicate.extract(|p| p.polarity)
}

pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
6 changes: 6 additions & 0 deletions compiler/rustc_infer/src/traits/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ use rustc_ast_ir::try_visit;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt};
use rustc_type_ir::traverse::{ImportantTypeTraversal, TypeTraversable};

use crate::traits;
use crate::traits::project::Normalized;
@@ -55,6 +56,11 @@ impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
}
}

impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeTraversable<TyCtxt<'tcx>>
for traits::Obligation<'tcx, O>
{
type Kind = ImportantTypeTraversal;
}
impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
for traits::Obligation<'tcx, O>
{
25 changes: 4 additions & 21 deletions compiler/rustc_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ mod diagnostics;
mod extension;
mod hash_stable;
mod lift;
mod noop_type_traversable;
mod query;
mod serialize;
mod symbols;
@@ -81,27 +82,9 @@ decl_derive!([TyDecodable] => serialize::type_decodable_derive);
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
decl_derive!(
[TypeFoldable, attributes(type_foldable)] =>
/// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).
///
/// The fold will produce a value of the same struct or enum variant as the input, with
/// each field respectively folded using the `TypeFoldable` implementation for its type.
/// However, if a field of a struct or an enum variant is annotated with
/// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its
/// type is not required to implement `TypeFoldable`).
type_foldable::type_foldable_derive
);
decl_derive!(
[TypeVisitable, attributes(type_visitable)] =>
/// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported).
///
/// Each field of the struct or enum variant will be visited in definition order, using the
/// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum
/// variant is annotated with `#[type_visitable(ignore)]` then that field will not be
/// visited (and its type is not required to implement `TypeVisitable`).
type_visitable::type_visitable_derive
);
decl_derive!([NoopTypeTraversable] => noop_type_traversable::noop_type_traversable_derive);
decl_derive!([TypeVisitable] => type_visitable::type_visitable_derive);
decl_derive!([TypeFoldable] => type_foldable::type_foldable_derive);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
decl_derive!(
[Diagnostic, attributes(
39 changes: 39 additions & 0 deletions compiler/rustc_macros/src/noop_type_traversable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use quote::quote;
use syn::parse_quote;

pub(super) fn noop_type_traversable_derive(
mut s: synstructure::Structure<'_>,
) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}

s.underscore_const(true);

if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! { 'tcx });
}

s.add_bounds(synstructure::AddBounds::None);
let mut where_clauses = None;
s.add_trait_bounds(
&parse_quote!(
::rustc_middle::ty::traverse::TypeTraversable<
::rustc_middle::ty::TyCtxt<'tcx>,
Kind = ::rustc_middle::ty::traverse::NoopTypeTraversal,
>
),
&mut where_clauses,
synstructure::AddBounds::Fields,
);
for pred in where_clauses.into_iter().flat_map(|c| c.predicates) {
s.add_where_predicate(pred);
}

s.bound_impl(
quote!(::rustc_middle::ty::traverse::TypeTraversable<::rustc_middle::ty::TyCtxt<'tcx>>),
quote! {
type Kind = ::rustc_middle::ty::traverse::NoopTypeTraversal;
},
)
}
Loading