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
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_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
};

Expand Down
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
Expand Up @@ -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,
)
}
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
};

Expand Down
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
Expand Up @@ -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"),
};

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/middle/exported_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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));
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"
Expand All @@ -510,7 +518,7 @@ impl<'tcx> Instance<'tcx> {
}
});

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

#[inline]
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -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))
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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!(),
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_smir/src/rustc_smir/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_symbol_mangling/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
);
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) => {
Expand All @@ -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)
}
Expand Down
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
Expand Up @@ -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,
Expand Down
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>>();
}
Loading