Skip to content

Resolve instance for SymFn in global/naked asm #140374

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

Merged
merged 2 commits into from
May 6, 2025
Merged
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_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
@@ -1282,7 +1282,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
intrinsic.name,
);
}
return Err(Instance::new(instance.def_id(), instance.args));
return Err(Instance::new_raw(instance.def_id(), instance.args));
}
}

2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
@@ -399,7 +399,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}

// Fall back to default body
_ => return Err(Instance::new(instance.def_id(), instance.args)),
_ => return Err(Instance::new_raw(instance.def_id(), instance.args)),
};

if !fn_abi.ret.is_ignore() {
Original file line number Diff line number Diff line change
@@ -157,7 +157,7 @@ fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty:
let def_id = local_def_id.to_def_id();

// Make a dummy instance that fills in all generics with placeholders.
ty::Instance::new(
ty::Instance::new_raw(
def_id,
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
if let ty::GenericParamDefKind::Lifetime = param.kind {
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -613,7 +613,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
_ => {
debug!("unknown intrinsic '{}' -- falling back to default body", name);
// Call the fallback body instead of generating the intrinsic code
return Err(ty::Instance::new(instance.def_id(), instance.args));
return Err(ty::Instance::new_raw(instance.def_id(), instance.args));
}
};

4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
@@ -612,7 +612,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
ExportedSymbol::Generic(def_id, args) => {
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
tcx,
Instance::new(def_id, args),
Instance::new_raw(def_id, args),
instantiating_crate,
)
}
@@ -660,7 +660,7 @@ fn calling_convention_for_symbol<'tcx>(
None
}
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
ExportedSymbol::Generic(def_id, args) => Some(Instance::new_raw(def_id, args)),
// DropGlue always use the Rust calling convention and thus follow the target's default
// symbol decoration scheme.
ExportedSymbol::DropGlue(..) => None,
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
@@ -457,7 +457,13 @@ where
rustc_hir::InlineAsmOperand::SymFn { expr } => {
let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
let instance = match ty.kind() {
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
&ty::FnDef(def_id, args) => Instance::expect_resolve(
cx.tcx(),
ty::TypingEnv::fully_monomorphized(),
def_id,
args,
expr.span,
),
_ => span_bug!(*op_sp, "asm sym is not a function"),
};

4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
@@ -95,7 +95,9 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL
);

let instance = match mono_type.kind() {
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
&ty::FnDef(def_id, args) => {
Instance::expect_resolve(cx.tcx(), cx.typing_env(), def_id, args, value.span)
}
_ => bug!("asm sym is not a function"),
};

2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -216,7 +216,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
check::maybe_check_static_with_link_section(tcx, item_def_id);
}
DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
let cid = GlobalId { instance, promoted: None };
let typing_env = ty::TypingEnv::fully_monomorphized();
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ impl ClashingExternDeclarations {
/// for the item, return its HirId without updating the set.
fn insert(&mut self, tcx: TyCtxt<'_>, fi: hir::ForeignItemId) -> Option<hir::OwnerId> {
let did = fi.owner_id.to_def_id();
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
let instance = Instance::new_raw(did, ty::List::identity_for_item(tcx, did));
let name = Symbol::intern(tcx.symbol_name(instance).name);
if let Some(&existing_id) = self.seen_decls.get(&name) {
// Avoid updating the map with the new entry when we do find a collision. We want to
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/middle/exported_symbols.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ impl<'tcx> ExportedSymbol<'tcx> {
match *self {
ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
ExportedSymbol::Generic(def_id, args) => {
tcx.symbol_name(ty::Instance::new(def_id, args))
tcx.symbol_name(ty::Instance::new_raw(def_id, args))
}
ExportedSymbol::DropGlue(ty) => {
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ impl<'tcx> TyCtxt<'tcx> {
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
// encountered.
let args = GenericArgs::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, args);
let instance = ty::Instance::new_raw(def_id, args);
let cid = GlobalId { instance, promoted: None };
let typing_env = ty::TypingEnv::post_analysis(self, def_id);
self.const_eval_global_id(typing_env, cid, DUMMY_SP)
@@ -39,7 +39,7 @@ impl<'tcx> TyCtxt<'tcx> {
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
// encountered.
let args = GenericArgs::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, args);
let instance = ty::Instance::new_raw(def_id, args);
let cid = GlobalId { instance, promoted: None };
let typing_env = ty::TypingEnv::post_analysis(self, def_id);
let inputs = self.erase_regions(typing_env.as_query_input(cid));
@@ -209,7 +209,7 @@ impl<'tcx> TyCtxtEnsureOk<'tcx> {
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
// encountered.
let args = GenericArgs::identity_for_item(self.tcx, def_id);
let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args));
let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args));
let cid = GlobalId { instance, promoted: None };
let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id);
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
@@ -318,7 +318,7 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> {
match *self {
MonoItem::Fn(instance) => write!(f, "fn {instance}"),
MonoItem::Static(def_id) => {
write!(f, "static {}", Instance::new(def_id, GenericArgs::empty()))
write!(f, "static {}", Instance::new_raw(def_id, GenericArgs::empty()))
}
MonoItem::GlobalAsm(..) => write!(f, "global_asm"),
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -2481,7 +2481,7 @@ rustc_queries! {
query resolve_instance_raw(
key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) }
}

query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
18 changes: 13 additions & 5 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
@@ -491,7 +491,15 @@ fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> {
}

impl<'tcx> Instance<'tcx> {
pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
/// Creates a new [`InstanceKind::Item`] from the `def_id` and `args`.
///
/// Note that this item corresponds to the body of `def_id` directly, which
/// likely does not make sense for trait items which need to be resolved to an
/// implementation, and which may not even have a body themselves. Usages of
/// this function should probably use [`Instance::expect_resolve`], or if run
/// in a polymorphic environment or within a lint (that may encounter ambiguity)
/// [`Instance::try_resolve`] instead.
pub fn new_raw(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
assert!(
!args.has_escaping_bound_vars(),
"args of instance {def_id:?} has escaping bound vars: {args:?}"
@@ -510,7 +518,7 @@ impl<'tcx> Instance<'tcx> {
}
});

Instance::new(def_id, args)
Instance::new_raw(def_id, args)
}

#[inline]
@@ -603,7 +611,7 @@ impl<'tcx> Instance<'tcx> {
let type_length = type_length(args);
if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) =
shrunk_instance_name(tcx, Instance::new(def_id, args));
shrunk_instance_name(tcx, Instance::new_raw(def_id, args));
let mut path = PathBuf::new();
let was_written = if let Some(path2) = written_to_path {
path = path2;
@@ -773,7 +781,7 @@ impl<'tcx> Instance<'tcx> {

match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
_ => Instance::new(def_id, args),
_ => Instance::new_raw(def_id, args),
}
}

@@ -899,7 +907,7 @@ impl<'tcx> Instance<'tcx> {
// This is important for `Iterator`'s combinators, but also useful for
// adding future default methods to `Future`, for instance.
debug_assert!(tcx.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_args))
Some(Instance::new_raw(trait_item_id, rcvr_args))
}
}

4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
@@ -931,7 +931,7 @@ fn visit_instance_use<'tcx>(
// We explicitly skip this otherwise to ensure we get a linker error
// if anyone tries to call this intrinsic and the codegen backend did not
// override the implementation.
let instance = ty::Instance::new(instance.def_id(), instance.args);
let instance = ty::Instance::new_raw(instance.def_id(), instance.args);
if tcx.should_codegen_locally(instance) {
output.push(create_fn_mono_item(tcx, instance, source));
}
@@ -1520,7 +1520,7 @@ impl<'v> RootCollector<'_, 'v> {
ty::Closure(def_id, args)
| ty::Coroutine(def_id, args)
| ty::CoroutineClosure(def_id, args) => {
Instance::new(def_id, self.tcx.erase_regions(args))
Instance::new_raw(def_id, self.tcx.erase_regions(args))
}
_ => unreachable!(),
};
2 changes: 1 addition & 1 deletion compiler/rustc_smir/src/rustc_smir/builder.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ impl<'tcx> BodyBuilder<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
let instance = match instance.def {
// To get the fallback body of an intrinsic, we need to convert it to an item.
ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new_raw(def_id, instance.args),
_ => instance,
};
BodyBuilder { tcx, instance }
2 changes: 1 addition & 1 deletion compiler/rustc_symbol_mangling/src/test.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ impl SymbolNamesTest<'_> {
// some subset.
for attr in tcx.get_attrs(def_id, SYMBOL_NAME) {
let def_id = def_id.to_def_id();
let instance = Instance::new(
let instance = Instance::new_raw(
def_id,
tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)),
);
10 changes: 5 additions & 5 deletions compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
@@ -235,7 +235,7 @@ fn resolve_associated_item<'tcx>(
tcx.ensure_ok().compare_impl_item(leaf_def_item)?;
}

Some(ty::Instance::new(leaf_def.item.def_id, args))
Some(ty::Instance::new_raw(leaf_def.item.def_id, args))
}
traits::ImplSource::Builtin(BuiltinImplSource::Object(_), _) => {
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args);
@@ -280,7 +280,7 @@ fn resolve_associated_item<'tcx>(

// Use the default `fn clone_from` from `trait Clone`.
let args = tcx.erase_regions(rcvr_args);
Some(ty::Instance::new(trait_item_id, args))
Some(ty::Instance::new_raw(trait_item_id, args))
}
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) {
if tcx.is_lang_item(trait_item_id, LangItem::FnPtrAddr) {
@@ -329,7 +329,7 @@ fn resolve_associated_item<'tcx>(
// sync with the built-in trait implementations (since all of the
// implementations return `FnOnce::Output`).
if ty::ClosureKind::FnOnce == args.as_coroutine_closure().kind() {
Some(Instance::new(coroutine_closure_def_id, args))
Some(Instance::new_raw(coroutine_closure_def_id, args))
} else {
Some(Instance {
def: ty::InstanceKind::ConstructCoroutineInClosureShim {
@@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>(
args,
})
} else {
Some(Instance::new(coroutine_closure_def_id, args))
Some(Instance::new_raw(coroutine_closure_def_id, args))
}
}
ty::Closure(closure_def_id, args) => {
@@ -381,7 +381,7 @@ fn resolve_associated_item<'tcx>(
let name = tcx.item_name(trait_item_id);
assert_eq!(name, sym::transmute);
let args = tcx.erase_regions(rcvr_args);
Some(ty::Instance::new(trait_item_id, args))
Some(ty::Instance::new_raw(trait_item_id, args))
} else {
Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
}
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/non_copy_const.rs
Original file line number Diff line number Diff line change
@@ -263,7 +263,7 @@ impl<'tcx> NonCopyConst<'tcx> {
fn is_value_unfrozen_poly(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
let def_id = body_id.hir_id.owner.to_def_id();
let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id);
let instance = ty::Instance::new(def_id, args);
let instance = ty::Instance::new_raw(def_id, args);
let cid = GlobalId {
instance,
promoted: None,
27 changes: 27 additions & 0 deletions tests/ui/asm/global-asm-mono-sym-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Test that we're properly monomorphizing sym args in global asm blocks
// that point to associated items.

//@ edition: 2021
//@ needs-asm-support
//@ only-x86_64-unknown-linux-gnu
//@ build-pass

#![no_main]

use std::arch::global_asm;

fn foo() {
loop {}
}

trait Foo {
fn bar();
}

impl Foo for i32 {
fn bar() {
loop {}
}
}

global_asm!(".global main", "main:", "call {}", sym <i32 as Foo>::bar);
35 changes: 35 additions & 0 deletions tests/ui/asm/naked-asm-mono-sym-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Regression test for <https://github.com/rust-lang/rust/issues/140373>.
// Test that we're properly monomorphizing sym args in naked asm blocks
// that point to associated items.

//@ edition: 2021
//@ needs-asm-support
//@ only-x86_64
//@ build-pass

trait Tr {
extern "C" fn t();
}

enum E<const C: usize> {}

impl<const C: usize> Tr for E<C> {
extern "C" fn t() {
println!("Const generic: {}", C);
}
}

#[unsafe(naked)]
extern "C" fn foo<U: Tr>() {
core::arch::naked_asm!(
"push rax",
"call {fn}",
"pop rax",
"ret",
fn = sym <U as Tr>::t,
);
}

fn main() {
foo::<E<42>>();
}