Skip to content
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

'improve' type traversal #132046

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
Expand Up @@ -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)),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))),
);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
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};

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() => {
Expand Down
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
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;

Expand Down
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
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
})
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
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
Expand Up @@ -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};
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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 })
}
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>> {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_infer/src/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>
{
Expand Down
25 changes: 4 additions & 21 deletions compiler/rustc_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod diagnostics;
mod extension;
mod hash_stable;
mod lift;
mod noop_type_traversable;
mod query;
mod serialize;
mod symbols;
Expand Down Expand Up @@ -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(
Expand Down
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
Loading