Rollup merge of #140374 - compiler-errors:global_asm-bug, r=lcnr
Resolve instance for SymFn in global/naked asm `Instance::expect_resolve` ensures that we're actually going from trait item -> impl item. Fixes #140373
This commit is contained in:
commit
1e90557ae8
21 changed files with 109 additions and 31 deletions
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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!(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
tests/ui/asm/global-asm-mono-sym-fn.rs
Normal file
27
tests/ui/asm/global-asm-mono-sym-fn.rs
Normal file
|
|
@ -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
tests/ui/asm/naked-asm-mono-sym-fn.rs
Normal file
35
tests/ui/asm/naked-asm-mono-sym-fn.rs
Normal file
|
|
@ -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…
Add table
Add a link
Reference in a new issue