diff --git a/RELEASES.md b/RELEASES.md
index 2b65d070d5fd1..aa5f37fffebff 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,5 +1,5 @@
-Version 1.90 (2025-09-18)
-==========================
+Version 1.90.0 (2025-09-18)
+===========================
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index e5405a7ad910c..5e10c5a77d97d 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -64,8 +64,6 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
-ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
-
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
.label = `extern "{$abi}"` because of this
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index dc221c2fb1abc..f773b02058ef1 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -696,7 +696,7 @@ impl<'a> AstValidator<'a> {
match fn_ctxt {
FnCtxt::Foreign => return,
- FnCtxt::Free => match sig.header.ext {
+ FnCtxt::Free | FnCtxt::Assoc(_) => match sig.header.ext {
Extern::Implicit(_) => {
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
@@ -726,11 +726,6 @@ impl<'a> AstValidator<'a> {
self.dcx().emit_err(err);
}
},
- FnCtxt::Assoc(_) => {
- // For now, C variable argument lists are unsupported in associated functions.
- let err = errors::CVariadicAssociatedFunction { span: variadic_param.span };
- self.dcx().emit_err(err);
- }
}
}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index e09ca5b81c80c..fd75e999d1381 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -318,13 +318,6 @@ pub(crate) struct ExternItemAscii {
pub block: Span,
}
-#[derive(Diagnostic)]
-#[diag(ast_passes_c_variadic_associated_function)]
-pub(crate) struct CVariadicAssociatedFunction {
- #[primary_span]
- pub span: Span,
-}
-
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_no_extern)]
#[help]
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs
index 94379cdebf730..6be90994015f3 100644
--- a/compiler/rustc_borrowck/src/handle_placeholders.rs
+++ b/compiler/rustc_borrowck/src/handle_placeholders.rs
@@ -166,13 +166,9 @@ impl RegionTracker {
}
}
- /// Determine if the tracked universes of the two SCCs are compatible.
- pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
- // HACK: We first check whether we can name the highest existential universe
- // of `other`. This only exists to avoid errors in case that scc already
- // depends on a placeholder it cannot name itself.
- self.max_nameable_universe().can_name(other.max_nameable_universe())
- || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
+ /// Determine if we can name all the placeholders in `other`.
+ pub(crate) fn can_name_all_placeholders(&self, other: Self) -> bool {
+ other.reachable_placeholders.can_be_named_by(self.max_nameable_universe.0)
}
/// If this SCC reaches a placeholder it can't name, return it.
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f57456949bb5e..5f4bfd9df48e5 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -571,11 +571,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
- /// Returns `true` if all the elements in the value of `scc_b` are nameable
+ /// Returns `true` if all the placeholders in the value of `scc_b` are nameable
/// in `scc_a`. Used during constraint propagation, and only once
/// the value of `scc_b` has been computed.
- fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
- self.scc_annotations[scc_a].universe_compatible_with(self.scc_annotations[scc_b])
+ fn can_name_all_placeholders(
+ &self,
+ scc_a: ConstraintSccIndex,
+ scc_b: ConstraintSccIndex,
+ ) -> bool {
+ self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b])
}
/// Once regions have been propagated, this method is used to see
@@ -964,16 +968,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return true;
}
+ let fr_static = self.universal_regions().fr_static;
+
// If we are checking that `'sup: 'sub`, and `'sub` contains
// some placeholder that `'sup` cannot name, then this is only
// true if `'sup` outlives static.
- if !self.universe_compatible(sub_region_scc, sup_region_scc) {
+ //
+ // Avoid infinite recursion if `sub_region` is already `'static`
+ if sub_region != fr_static
+ && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc)
+ {
debug!(
"sub universe `{sub_region_scc:?}` is not nameable \
by super `{sup_region_scc:?}`, promoting to static",
);
- return self.eval_outlives(sup_region, self.universal_regions().fr_static);
+ return self.eval_outlives(sup_region, fr_static);
}
// Both the `sub_region` and `sup_region` consist of the union
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 2627ed899a933..aece0bda34692 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -230,8 +230,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
location: impl NormalizeLocation,
) -> Ty<'tcx> {
let tcx = self.tcx();
+ let body = self.body;
+
+ let cause = ObligationCause::misc(
+ location.to_locations().span(body),
+ body.source.def_id().expect_local(),
+ );
+
if self.infcx.next_trait_solver() {
- let body = self.body;
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
@@ -241,10 +247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|ocx| {
let structurally_normalize = |ty| {
ocx.structurally_normalize_ty(
- &ObligationCause::misc(
- location.to_locations().span(body),
- body.source.def_id().expect_local(),
- ),
+ &cause,
param_env,
ty,
)
@@ -253,6 +256,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let tail = tcx.struct_tail_raw(
ty,
+ &cause,
structurally_normalize,
|| {},
);
@@ -265,7 +269,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
} else {
let mut normalize = |ty| self.normalize(ty, location);
- let tail = tcx.struct_tail_raw(ty, &mut normalize, || {});
+ let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
normalize(tail)
}
}
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 37c6c4a61d8d6..7c41258ebfe5f 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -1,6 +1,7 @@
use rustc_abi::{BackendRepr, FieldIdx, VariantIdx};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError};
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::layout::{LayoutCx, TyAndLayout};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir};
@@ -196,6 +197,7 @@ fn reconstruct_place_meta<'tcx>(
// Traverse the type, and update `last_valtree` as we go.
let tail = tcx.struct_tail_raw(
layout.ty,
+ &ObligationCause::dummy(),
|ty| ty,
|| {
let branches = last_valtree.unwrap_branch();
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 6d95b6917e296..2fbea5b61cfc6 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -1,3 +1,4 @@
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
@@ -74,8 +75,14 @@ impl<'a, 'tcx> Expectation<'tcx> {
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
/// for examples of where this comes up,.
pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+ let span = match ty.kind() {
+ ty::Adt(adt_def, _) => fcx.tcx.def_span(adt_def.did()),
+ _ => fcx.tcx.def_span(fcx.body_id),
+ };
+ let cause = ObligationCause::misc(span, fcx.body_id);
+
// FIXME: This is not right, even in the old solver...
- match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() {
+ match fcx.tcx.struct_tail_raw(ty, &cause, |ty| ty, || {}).kind() {
ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
_ => ExpectHasType(ty),
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 7370124e800da..4563159314d15 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -424,6 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !ty.references_error() {
let tail = self.tcx.struct_tail_raw(
ty,
+ &self.misc(span),
|ty| {
if self.next_trait_solver() {
self.try_structurally_resolve_type(span, ty)
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index dad402ec69616..e3e1393b5f9ae 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -71,6 +71,8 @@ pub enum TypeMismatchReason {
#[diag(middle_recursion_limit_reached)]
#[help]
pub(crate) struct RecursionLimitReached<'tcx> {
+ #[primary_span]
+ pub span: Span,
pub ty: Ty<'tcx>,
pub suggested_limit: rustc_hir::limit::Limit,
}
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index ab8a314295392..0c7bddf60d974 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -823,6 +823,9 @@ impl DynCompatibilityViolation {
DynCompatibilityViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
format!("method `{name}` is `async`").into()
}
+ DynCompatibilityViolation::Method(name, MethodViolationCode::CVariadic, _) => {
+ format!("method `{name}` is C-variadic").into()
+ }
DynCompatibilityViolation::Method(
name,
MethodViolationCode::WhereClauseReferencesSelf,
@@ -977,6 +980,9 @@ pub enum MethodViolationCode {
/// e.g., `fn foo()`
Generic,
+ /// e.g., `fn (mut ap: ...)`
+ CVariadic,
+
/// the method's receiver (`self` argument) can't be dispatched on
UndispatchableReceiver(Option),
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 9524057eebc6c..c477e65f5d6b3 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -22,6 +22,7 @@ use {rustc_abi as abi, rustc_hir as hir};
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::TyCtxtAt;
+use crate::traits::ObligationCause;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt};
@@ -384,6 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let tail = tcx.struct_tail_raw(
pointee,
+ &ObligationCause::dummy(),
|ty| match tcx.try_normalize_erasing_regions(typing_env, ty) {
Ok(ty) => ty,
Err(e) => Ty::new_error_with_message(
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 2bea797799958..de35e5e847c81 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -23,6 +23,7 @@ use ty::util::IntTypeExt;
use super::GenericParamDefKind;
use crate::infer::canonical::Canonical;
+use crate::traits::ObligationCause;
use crate::ty::InferTy::*;
use crate::ty::{
self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
@@ -1638,7 +1639,7 @@ impl<'tcx> Ty<'tcx> {
tcx: TyCtxt<'tcx>,
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
) -> Result, Ty<'tcx>> {
- let tail = tcx.struct_tail_raw(self, normalize, || {});
+ let tail = tcx.struct_tail_raw(self, &ObligationCause::dummy(), normalize, || {});
match tail.kind() {
// Sized types
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b79b67c5927b0..4f039381e500d 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -24,6 +24,7 @@ use super::TypingEnv;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
use crate::query::Providers;
+use crate::traits::ObligationCause;
use crate::ty::layout::{FloatExt, IntegerExt};
use crate::ty::{
self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
@@ -216,7 +217,12 @@ impl<'tcx> TyCtxt<'tcx> {
typing_env: ty::TypingEnv<'tcx>,
) -> Ty<'tcx> {
let tcx = self;
- tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {})
+ tcx.struct_tail_raw(
+ ty,
+ &ObligationCause::dummy(),
+ |ty| tcx.normalize_erasing_regions(typing_env, ty),
+ || {},
+ )
}
/// Returns true if a type has metadata.
@@ -248,6 +254,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn struct_tail_raw(
self,
mut ty: Ty<'tcx>,
+ cause: &ObligationCause<'tcx>,
mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
// This is currently used to allow us to walk a ValTree
// in lockstep with the type in order to get the ValTree branch that
@@ -261,9 +268,11 @@ impl<'tcx> TyCtxt<'tcx> {
Limit(0) => Limit(2),
limit => limit * 2,
};
- let reported = self
- .dcx()
- .emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
+ let reported = self.dcx().emit_err(crate::error::RecursionLimitReached {
+ span: cause.span,
+ ty,
+ suggested_limit,
+ });
return Ty::new_error(self, reported);
}
match *ty.kind() {
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index bcd11d6918d9a..3260dd712b9e4 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -426,6 +426,9 @@ fn virtual_call_violations_for_method<'tcx>(
if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
errors.push(code);
}
+ if sig.skip_binder().c_variadic {
+ errors.push(MethodViolationCode::CVariadic);
+ }
// We can't monomorphize things like `fn foo(...)`.
let own_counts = tcx.generics_of(method.def_id).own_counts();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 884d53732fe2a..042d6def84c33 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1057,6 +1057,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
Some(LangItem::PointeeTrait) => {
let tail = selcx.tcx().struct_tail_raw(
self_ty,
+ &obligation.cause,
|ty| {
// We throw away any obligations we get from this, since we normalize
// and confirm these obligations once again during confirmation
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 643e3db8f83fe..c4cb43011adb0 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -10,6 +10,7 @@ use rustc_hashes::Hash64;
use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::query::Providers;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::layout::{
FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout,
};
@@ -390,30 +391,31 @@ fn layout_of_uncached<'tcx>(
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
- let metadata_ty =
- match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) {
- Ok(metadata_ty) => metadata_ty,
- Err(mut err) => {
- // Usually `::Metadata` can't be normalized because
- // its struct tail cannot be normalized either, so try to get a
- // more descriptive layout error here, which will lead to less confusing
- // diagnostics.
- //
- // We use the raw struct tail function here to get the first tail
- // that is an alias, which is likely the cause of the normalization
- // error.
- match tcx.try_normalize_erasing_regions(
- cx.typing_env,
- tcx.struct_tail_raw(pointee, |ty| ty, || {}),
- ) {
- Ok(_) => {}
- Err(better_err) => {
- err = better_err;
- }
+ let metadata_ty = match tcx
+ .try_normalize_erasing_regions(cx.typing_env, pointee_metadata)
+ {
+ Ok(metadata_ty) => metadata_ty,
+ Err(mut err) => {
+ // Usually `::Metadata` can't be normalized because
+ // its struct tail cannot be normalized either, so try to get a
+ // more descriptive layout error here, which will lead to less confusing
+ // diagnostics.
+ //
+ // We use the raw struct tail function here to get the first tail
+ // that is an alias, which is likely the cause of the normalization
+ // error.
+ match tcx.try_normalize_erasing_regions(
+ cx.typing_env,
+ tcx.struct_tail_raw(pointee, &ObligationCause::dummy(), |ty| ty, || {}),
+ ) {
+ Ok(_) => {}
+ Err(better_err) => {
+ err = better_err;
}
- return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
}
- };
+ return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
+ }
+ };
let metadata_layout = cx.layout_of(metadata_ty)?;
// If the metadata is a 1-zst, then the pointer is thin.
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 18a9a7c22d9dd..e91e5055e9053 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -353,6 +353,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId)
let tail = tcx.struct_tail_raw(
tcx.type_of(impl_def_id).instantiate_identity(),
+ &cause,
|ty| {
ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
Ty::new_error_with_message(
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index 54e54f734f647..913f766ec1683 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -111,6 +111,13 @@ fn from_str_issue7588() {
assert_eq!(s, None);
}
+#[test]
+#[should_panic = "radix must lie in the range `[2, 36]`"]
+fn from_ascii_radix_panic() {
+ let radix = 1;
+ let _parsed = u64::from_str_radix("12345ABCD", radix);
+}
+
#[test]
fn test_int_from_str_overflow() {
test_parse::("127", Ok(127));
diff --git a/tests/ui/c-variadic/inherent-method.rs b/tests/ui/c-variadic/inherent-method.rs
new file mode 100644
index 0000000000000..537bae7b3f0f4
--- /dev/null
+++ b/tests/ui/c-variadic/inherent-method.rs
@@ -0,0 +1,45 @@
+//@ run-pass
+#![feature(c_variadic)]
+
+#[repr(transparent)]
+struct S(i32);
+
+impl S {
+ unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
+ unsafe { ap.arg() }
+ }
+
+ unsafe extern "C" fn method_owned(self, mut ap: ...) -> i32 {
+ self.0 + unsafe { ap.arg::() }
+ }
+
+ unsafe extern "C" fn method_ref(&self, mut ap: ...) -> i32 {
+ self.0 + unsafe { ap.arg::() }
+ }
+
+ unsafe extern "C" fn method_mut(&mut self, mut ap: ...) -> i32 {
+ self.0 + unsafe { ap.arg::() }
+ }
+
+ unsafe extern "C" fn fat_pointer(self: Box, mut ap: ...) -> i32 {
+ self.0 + unsafe { ap.arg::() }
+ }
+}
+
+fn main() {
+ unsafe {
+ assert_eq!(S::associated_function(32), 32);
+ assert_eq!(S(100).method_owned(32), 132);
+ assert_eq!(S(100).method_ref(32), 132);
+ assert_eq!(S(100).method_mut(32), 132);
+ assert_eq!(S::fat_pointer(Box::new(S(100)), 32), 132);
+
+ type Method = unsafe extern "C" fn(T, ...) -> i32;
+
+ assert_eq!((S::associated_function as unsafe extern "C" fn(...) -> i32)(32), 32);
+ assert_eq!((S::method_owned as Method<_>)(S(100), 32), 132);
+ assert_eq!((S::method_ref as Method<_>)(&S(100), 32), 132);
+ assert_eq!((S::method_mut as Method<_>)(&mut S(100), 32), 132);
+ assert_eq!((S::fat_pointer as Method<_>)(Box::new(S(100)), 32), 132);
+ }
+}
diff --git a/tests/ui/c-variadic/not-async.rs b/tests/ui/c-variadic/not-async.rs
index 45a7e1f8972bf..bdb51a9a43232 100644
--- a/tests/ui/c-variadic/not-async.rs
+++ b/tests/ui/c-variadic/not-async.rs
@@ -2,6 +2,14 @@
#![feature(c_variadic)]
#![crate_type = "lib"]
-async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
+async unsafe extern "C" fn fn_cannot_be_async(x: isize, ...) {}
//~^ ERROR functions cannot be both `async` and C-variadic
//~| ERROR hidden type for `impl Future