Skip to content
Merged
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
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
} else {
ty::List::empty()
};
let callee_fn_abi = self.fn_abi_of_instance(instance, extra_tys)?;
let callee_fn_abi = self.fn_abi_of_instance_no_deduced_attrs(instance, extra_tys)?;

if caller_fn_abi.conv != callee_fn_abi.conv {
throw_ub_custom!(
Expand Down Expand Up @@ -899,7 +899,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty);
ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
};
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
let fn_abi = self.fn_abi_of_instance_no_deduced_attrs(instance, ty::List::empty())?;

let arg = self.mplace_to_ref(&place)?;
let ret = MPlaceTy::fake_alloc_zst(self.layout_of(self.tcx.types.unit)?);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}

/// This inherent method takes priority over the trait method with the same name in FnAbiOf,
/// and allows wrapping the actual [FnAbiOf::fn_abi_of_instance] with a tracing span.
/// See [FnAbiOf::fn_abi_of_instance] for the original documentation.
/// and allows wrapping the actual [FnAbiOf::fn_abi_of_instance_no_deduced_attrs] with a tracing span.
/// See [FnAbiOf::fn_abi_of_instance_no_deduced_attrs] for the original documentation.
#[inline(always)]
pub fn fn_abi_of_instance(
pub fn fn_abi_of_instance_no_deduced_attrs(
&self,
instance: ty::Instance<'tcx>,
extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> <Self as FnAbiOfHelpers<'tcx>>::FnAbiOfResult {
let _trace = enter_trace_span!(M, layouting::fn_abi_of_instance, ?instance, ?extra_args);
FnAbiOf::fn_abi_of_instance(self, instance, extra_args)
FnAbiOf::fn_abi_of_instance_no_deduced_attrs(self, instance, extra_args)
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let instance = self.resolve(def_id, args)?;
(
FnVal::Instance(instance),
self.fn_abi_of_instance(instance, extra_args)?,
self.fn_abi_of_instance_no_deduced_attrs(instance, extra_args)?,
instance.def.requires_caller_location(*self.tcx),
)
}
Expand Down
36 changes: 31 additions & 5 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1801,12 +1801,38 @@ rustc_queries! {
desc { "computing call ABI of `{}` function pointers", key.value.0 }
}

/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
/// direct calls to an `fn`.
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for direct calls*
/// to an `fn`. Indirectly-passed parameters in the returned ABI might not include all possible
/// codegen optimization attributes (such as `ReadOnly` or `CapturesNone`), as deducing these
/// requires inspection of function bodies that can lead to cycles when performed during typeck.
/// Post typeck, you should prefer the optimized ABI returned by `TyCtxt::fn_abi_of_instance`.
///
/// NB: the ABI returned by this query must not differ from that returned by
/// `fn_abi_of_instance_raw` in any other way.
///
/// * that includes virtual calls, which are represented by "direct calls" to an
/// `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance_no_deduced_attrs(
key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing unadjusted call ABI of `{}`", key.value.0 }
}

/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for direct calls*
/// to an `fn`. Indirectly-passed parameters in the returned ABI will include applicable
/// codegen optimization attributes, including `ReadOnly` and `CapturesNone` -- deduction of
/// which requires inspection of function bodies that can lead to cycles when performed during
/// typeck. During typeck, you should therefore use instead the unoptimized ABI returned by
/// `fn_abi_of_instance_no_deduced_attrs`.
///
/// For performance reasons, you should prefer to call the inherent `TyCtxt::fn_abi_of_instance`
/// method rather than invoke this query: it delegates to this query if necessary, but where
/// possible delegates instead to the `fn_abi_of_instance_no_deduced_attrs` query (thus avoiding
/// unnecessary query system overhead).
///
/// NB: that includes virtual calls, which are represented by "direct calls"
/// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance(
/// * that includes virtual calls, which are represented by "direct calls" to an
/// `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance_raw(
key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}`", key.value.0 }
Expand Down
53 changes: 49 additions & 4 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,11 +1369,56 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
)
}

/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
/// direct calls to an `fn`.
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for direct calls*
/// to an `fn`. Indirectly-passed parameters in the returned ABI might not include all possible
/// codegen optimization attributes (such as `ReadOnly` or `CapturesNone`), as deducing these
/// requires inspection of function bodies that can lead to cycles when performed during typeck.
/// Post typeck, you should prefer the optimized ABI returned by `fn_abi_of_instance`.
///
/// NB: that includes virtual calls, which are represented by "direct calls"
/// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
/// NB: the ABI returned by this query must not differ from that returned by
/// `fn_abi_of_instance` in any other way.
///
/// * that includes virtual calls, which are represented by "direct calls" to an
/// `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
#[inline]
#[tracing::instrument(level = "debug", skip(self))]
fn fn_abi_of_instance_no_deduced_attrs(
&self,
instance: ty::Instance<'tcx>,
extra_args: &'tcx ty::List<Ty<'tcx>>,
) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span();
let tcx = self.tcx().at(span);

MaybeResult::from(
tcx.fn_abi_of_instance_no_deduced_attrs(
self.typing_env().as_query_input((instance, extra_args)),
)
.map_err(|err| {
// HACK(eddyb) at least for definitions of/calls to `Instance`s,
// we can get some kind of span even if one wasn't provided.
// However, we don't do this early in order to avoid calling
// `def_span` unconditionally (which may have a perf penalty).
let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
self.handle_fn_abi_err(
*err,
span,
FnAbiRequest::OfInstance { instance, extra_args },
)
}),
)
}

/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for direct calls*
/// to an `fn`. Indirectly-passed parameters in the returned ABI will include applicable
/// codegen optimization attributes, including `ReadOnly` and `CapturesNone` -- deduction of
/// which requires inspection of function bodies that can lead to cycles when performed during
/// typeck. During typeck, you should therefore use instead the unoptimized ABI returned by
/// `fn_abi_of_instance_no_deduced_attrs`.
///
/// * that includes virtual calls, which are represented by "direct calls" to an
/// `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
#[inline]
#[tracing::instrument(level = "debug", skip(self))]
fn fn_abi_of_instance(
Expand Down
32 changes: 31 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ use rustc_macros::{
TypeVisitable, extension,
};
use rustc_serialize::{Decodable, Encodable};
use rustc_session::config::OptLevel;
pub use rustc_session::lint::RegisteredTools;
use rustc_span::hygiene::MacroKind;
use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol};
use rustc_target::callconv::FnAbi;
pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet};
pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
#[allow(
Expand Down Expand Up @@ -120,7 +122,7 @@ use crate::ty;
use crate::ty::codec::{TyDecoder, TyEncoder};
pub use crate::ty::diagnostics::*;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::LayoutError;
use crate::ty::layout::{FnAbiError, LayoutError};
use crate::ty::util::Discr;
use crate::ty::walk::TypeWalker;

Expand Down Expand Up @@ -2167,6 +2169,34 @@ impl<'tcx> TyCtxt<'tcx> {

!self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty()
}

/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for direct calls*
/// to an `fn`. Indirectly-passed parameters in the returned ABI will include applicable
/// codegen optimization attributes, including `ReadOnly` and `CapturesNone` -- deduction of
/// which requires inspection of function bodies that can lead to cycles when performed during
/// typeck. During typeck, you should therefore use instead the unoptimized ABI returned by
/// `fn_abi_of_instance_no_deduced_attrs`.
///
/// For performance reasons, you should prefer to call this inherent method rather than invoke
/// the `fn_abi_of_instance_raw` query: it delegates to that query if necessary, but where
/// possible delegates instead to the `fn_abi_of_instance_no_deduced_attrs` query (thus avoiding
/// unnecessary query system overhead).
///
/// * that includes virtual calls, which are represented by "direct calls" to an
/// `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
#[inline]
pub fn fn_abi_of_instance(
self,
query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
// Only deduce attrs in full, optimized builds. Otherwise, avoid the query system overhead
// of ever invoking the `fn_abi_of_instance_raw` query.
if self.sess.opts.optimize != OptLevel::No && self.sess.opts.incremental.is_none() {
self.fn_abi_of_instance_raw(query)
} else {
self.fn_abi_of_instance_no_deduced_attrs(query)
}
}
}

pub fn provide(providers: &mut Providers) {
Expand Down
Loading
Loading