Skip to content

Commit 859591d

Browse files
Rollup merge of rust-lang#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 rust-lang#140373
2 parents 986ebd3 + 833c212 commit 859591d

File tree

21 files changed

+109
-31
lines changed

21 files changed

+109
-31
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
12821282
intrinsic.name,
12831283
);
12841284
}
1285-
return Err(Instance::new(instance.def_id(), instance.args));
1285+
return Err(Instance::new_raw(instance.def_id(), instance.args));
12861286
}
12871287
}
12881288

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
399399
}
400400

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

405405
if !fn_abi.ret.is_ignore() {

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty:
157157
let def_id = local_def_id.to_def_id();
158158

159159
// Make a dummy instance that fills in all generics with placeholders.
160-
ty::Instance::new(
160+
ty::Instance::new_raw(
161161
def_id,
162162
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
163163
if let ty::GenericParamDefKind::Lifetime = param.kind {

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
613613
_ => {
614614
debug!("unknown intrinsic '{}' -- falling back to default body", name);
615615
// Call the fallback body instead of generating the intrinsic code
616-
return Err(ty::Instance::new(instance.def_id(), instance.args));
616+
return Err(ty::Instance::new_raw(instance.def_id(), instance.args));
617617
}
618618
};
619619

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
612612
ExportedSymbol::Generic(def_id, args) => {
613613
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
614614
tcx,
615-
Instance::new(def_id, args),
615+
Instance::new_raw(def_id, args),
616616
instantiating_crate,
617617
)
618618
}
@@ -660,7 +660,7 @@ fn calling_convention_for_symbol<'tcx>(
660660
None
661661
}
662662
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
663-
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
663+
ExportedSymbol::Generic(def_id, args) => Some(Instance::new_raw(def_id, args)),
664664
// DropGlue always use the Rust calling convention and thus follow the target's default
665665
// symbol decoration scheme.
666666
ExportedSymbol::DropGlue(..) => None,

compiler/rustc_codegen_ssa/src/base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,13 @@ where
457457
rustc_hir::InlineAsmOperand::SymFn { expr } => {
458458
let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
459459
let instance = match ty.kind() {
460-
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
460+
&ty::FnDef(def_id, args) => Instance::expect_resolve(
461+
cx.tcx(),
462+
ty::TypingEnv::fully_monomorphized(),
463+
def_id,
464+
args,
465+
expr.span,
466+
),
461467
_ => span_bug!(*op_sp, "asm sym is not a function"),
462468
};
463469

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL
9595
);
9696

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

compiler/rustc_hir_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
216216
check::maybe_check_static_with_link_section(tcx, item_def_id);
217217
}
218218
DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
219-
let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
219+
let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
220220
let cid = GlobalId { instance, promoted: None };
221221
let typing_env = ty::TypingEnv::fully_monomorphized();
222222
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));

compiler/rustc_lint/src/foreign_modules.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl ClashingExternDeclarations {
104104
/// for the item, return its HirId without updating the set.
105105
fn insert(&mut self, tcx: TyCtxt<'_>, fi: hir::ForeignItemId) -> Option<hir::OwnerId> {
106106
let did = fi.owner_id.to_def_id();
107-
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
107+
let instance = Instance::new_raw(did, ty::List::identity_for_item(tcx, did));
108108
let name = Symbol::intern(tcx.symbol_name(instance).name);
109109
if let Some(&existing_id) = self.seen_decls.get(&name) {
110110
// Avoid updating the map with the new entry when we do find a collision. We want to

compiler/rustc_middle/src/middle/exported_symbols.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'tcx> ExportedSymbol<'tcx> {
5656
match *self {
5757
ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
5858
ExportedSymbol::Generic(def_id, args) => {
59-
tcx.symbol_name(ty::Instance::new(def_id, args))
59+
tcx.symbol_name(ty::Instance::new_raw(def_id, args))
6060
}
6161
ExportedSymbol::DropGlue(ty) => {
6262
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))

compiler/rustc_middle/src/mir/interpret/queries.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl<'tcx> TyCtxt<'tcx> {
2323
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
2424
// encountered.
2525
let args = GenericArgs::identity_for_item(self, def_id);
26-
let instance = ty::Instance::new(def_id, args);
26+
let instance = ty::Instance::new_raw(def_id, args);
2727
let cid = GlobalId { instance, promoted: None };
2828
let typing_env = ty::TypingEnv::post_analysis(self, def_id);
2929
self.const_eval_global_id(typing_env, cid, DUMMY_SP)
@@ -39,7 +39,7 @@ impl<'tcx> TyCtxt<'tcx> {
3939
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
4040
// encountered.
4141
let args = GenericArgs::identity_for_item(self, def_id);
42-
let instance = ty::Instance::new(def_id, args);
42+
let instance = ty::Instance::new_raw(def_id, args);
4343
let cid = GlobalId { instance, promoted: None };
4444
let typing_env = ty::TypingEnv::post_analysis(self, def_id);
4545
let inputs = self.erase_regions(typing_env.as_query_input(cid));
@@ -209,7 +209,7 @@ impl<'tcx> TyCtxtEnsureOk<'tcx> {
209209
// into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
210210
// encountered.
211211
let args = GenericArgs::identity_for_item(self.tcx, def_id);
212-
let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args));
212+
let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args));
213213
let cid = GlobalId { instance, promoted: None };
214214
let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id);
215215
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should

compiler/rustc_middle/src/mir/mono.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> {
318318
match *self {
319319
MonoItem::Fn(instance) => write!(f, "fn {instance}"),
320320
MonoItem::Static(def_id) => {
321-
write!(f, "static {}", Instance::new(def_id, GenericArgs::empty()))
321+
write!(f, "static {}", Instance::new_raw(def_id, GenericArgs::empty()))
322322
}
323323
MonoItem::GlobalAsm(..) => write!(f, "global_asm"),
324324
}

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2481,7 +2481,7 @@ rustc_queries! {
24812481
query resolve_instance_raw(
24822482
key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>
24832483
) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
2484-
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
2484+
desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) }
24852485
}
24862486

24872487
query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {

compiler/rustc_middle/src/ty/instance.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,15 @@ fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> {
491491
}
492492

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

513-
Instance::new(def_id, args)
521+
Instance::new_raw(def_id, args)
514522
}
515523

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

774782
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
775783
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
776-
_ => Instance::new(def_id, args),
784+
_ => Instance::new_raw(def_id, args),
777785
}
778786
}
779787

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

compiler/rustc_monomorphize/src/collector.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ fn visit_instance_use<'tcx>(
931931
// We explicitly skip this otherwise to ensure we get a linker error
932932
// if anyone tries to call this intrinsic and the codegen backend did not
933933
// override the implementation.
934-
let instance = ty::Instance::new(instance.def_id(), instance.args);
934+
let instance = ty::Instance::new_raw(instance.def_id(), instance.args);
935935
if tcx.should_codegen_locally(instance) {
936936
output.push(create_fn_mono_item(tcx, instance, source));
937937
}
@@ -1520,7 +1520,7 @@ impl<'v> RootCollector<'_, 'v> {
15201520
ty::Closure(def_id, args)
15211521
| ty::Coroutine(def_id, args)
15221522
| ty::CoroutineClosure(def_id, args) => {
1523-
Instance::new(def_id, self.tcx.erase_regions(args))
1523+
Instance::new_raw(def_id, self.tcx.erase_regions(args))
15241524
}
15251525
_ => unreachable!(),
15261526
};

compiler/rustc_smir/src/rustc_smir/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl<'tcx> BodyBuilder<'tcx> {
2222
pub(crate) fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
2323
let instance = match instance.def {
2424
// To get the fallback body of an intrinsic, we need to convert it to an item.
25-
ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
25+
ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new_raw(def_id, instance.args),
2626
_ => instance,
2727
};
2828
BodyBuilder { tcx, instance }

compiler/rustc_symbol_mangling/src/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl SymbolNamesTest<'_> {
5656
// some subset.
5757
for attr in tcx.get_attrs(def_id, SYMBOL_NAME) {
5858
let def_id = def_id.to_def_id();
59-
let instance = Instance::new(
59+
let instance = Instance::new_raw(
6060
def_id,
6161
tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)),
6262
);

compiler/rustc_ty_utils/src/instance.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ fn resolve_associated_item<'tcx>(
235235
tcx.ensure_ok().compare_impl_item(leaf_def_item)?;
236236
}
237237

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

281281
// Use the default `fn clone_from` from `trait Clone`.
282282
let args = tcx.erase_regions(rcvr_args);
283-
Some(ty::Instance::new(trait_item_id, args))
283+
Some(ty::Instance::new_raw(trait_item_id, args))
284284
}
285285
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) {
286286
if tcx.is_lang_item(trait_item_id, LangItem::FnPtrAddr) {
@@ -329,7 +329,7 @@ fn resolve_associated_item<'tcx>(
329329
// sync with the built-in trait implementations (since all of the
330330
// implementations return `FnOnce::Output`).
331331
if ty::ClosureKind::FnOnce == args.as_coroutine_closure().kind() {
332-
Some(Instance::new(coroutine_closure_def_id, args))
332+
Some(Instance::new_raw(coroutine_closure_def_id, args))
333333
} else {
334334
Some(Instance {
335335
def: ty::InstanceKind::ConstructCoroutineInClosureShim {
@@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>(
362362
args,
363363
})
364364
} else {
365-
Some(Instance::new(coroutine_closure_def_id, args))
365+
Some(Instance::new_raw(coroutine_closure_def_id, args))
366366
}
367367
}
368368
ty::Closure(closure_def_id, args) => {
@@ -381,7 +381,7 @@ fn resolve_associated_item<'tcx>(
381381
let name = tcx.item_name(trait_item_id);
382382
assert_eq!(name, sym::transmute);
383383
let args = tcx.erase_regions(rcvr_args);
384-
Some(ty::Instance::new(trait_item_id, args))
384+
Some(ty::Instance::new_raw(trait_item_id, args))
385385
} else {
386386
Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
387387
}

src/tools/clippy/clippy_lints/src/non_copy_const.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ impl<'tcx> NonCopyConst<'tcx> {
263263
fn is_value_unfrozen_poly(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
264264
let def_id = body_id.hir_id.owner.to_def_id();
265265
let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id);
266-
let instance = ty::Instance::new(def_id, args);
266+
let instance = ty::Instance::new_raw(def_id, args);
267267
let cid = GlobalId {
268268
instance,
269269
promoted: None,
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Test that we're properly monomorphizing sym args in global asm blocks
2+
// that point to associated items.
3+
4+
//@ edition: 2021
5+
//@ needs-asm-support
6+
//@ only-x86_64-unknown-linux-gnu
7+
//@ build-pass
8+
9+
#![no_main]
10+
11+
use std::arch::global_asm;
12+
13+
fn foo() {
14+
loop {}
15+
}
16+
17+
trait Foo {
18+
fn bar();
19+
}
20+
21+
impl Foo for i32 {
22+
fn bar() {
23+
loop {}
24+
}
25+
}
26+
27+
global_asm!(".global main", "main:", "call {}", sym <i32 as Foo>::bar);

tests/ui/asm/naked-asm-mono-sym-fn.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/140373>.
2+
// Test that we're properly monomorphizing sym args in naked asm blocks
3+
// that point to associated items.
4+
5+
//@ edition: 2021
6+
//@ needs-asm-support
7+
//@ only-x86_64
8+
//@ build-pass
9+
10+
trait Tr {
11+
extern "C" fn t();
12+
}
13+
14+
enum E<const C: usize> {}
15+
16+
impl<const C: usize> Tr for E<C> {
17+
extern "C" fn t() {
18+
println!("Const generic: {}", C);
19+
}
20+
}
21+
22+
#[unsafe(naked)]
23+
extern "C" fn foo<U: Tr>() {
24+
core::arch::naked_asm!(
25+
"push rax",
26+
"call {fn}",
27+
"pop rax",
28+
"ret",
29+
fn = sym <U as Tr>::t,
30+
);
31+
}
32+
33+
fn main() {
34+
foo::<E<42>>();
35+
}

0 commit comments

Comments
 (0)