Auto merge of #149322 - matthiaskrgr:rollup-uf0hmx6, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#147736 (Stabilize `asm_cfg`)
 - rust-lang/rust#148652 (Cleanup and refactor FnCtxt::report_no_match_method_error)
 - rust-lang/rust#149167 (skip checking supertraits in object candidate for `NormalizesTo` goal)
 - rust-lang/rust#149210 (fix: Do not ICE on normalization failure of an extern static item)
 - rust-lang/rust#149268 (add implementation-internal namespace for globalasm)
 - rust-lang/rust#149274 (Fix invalid link generation for type alias methods)
 - rust-lang/rust#149302 (Fix comment wording in simplify_comparison_integral.rs)
 - rust-lang/rust#149305 (Simplify OnceCell Clone impl)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-11-25 17:52:25 +00:00
commit 80d8f292d8
25 changed files with 488 additions and 305 deletions

View file

@ -3,8 +3,6 @@ builtin_macros_alloc_must_statics = allocators must be statics
builtin_macros_asm_attribute_not_supported =
this attribute is not supported on assembly
builtin_macros_asm_cfg =
the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
builtin_macros_asm_clobber_abi = clobber_abi
builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs

View file

@ -6,14 +6,13 @@ use rustc_expand::base::*;
use rustc_index::bit_set::GrowableBitSet;
use rustc_parse::parser::asm::*;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym};
use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec;
use {rustc_ast as ast, rustc_parse_format as parse};
use crate::errors;
use crate::util::{ExprToSpannedString, expr_to_spanned_string};
use crate::{errors, fluent_generated as fluent};
/// Validated assembly arguments, ready for macro expansion.
struct ValidatedAsmArgs {
@ -64,22 +63,13 @@ fn validate_asm_args<'a>(
for arg in args {
for attr in arg.attributes.0.iter() {
match attr.name() {
Some(sym::cfg | sym::cfg_attr) => {
if !ecx.ecfg.features.asm_cfg() {
let span = attr.span();
feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg)
.emit();
}
}
_ => {
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
}
if !matches!(attr.name(), Some(sym::cfg | sym::cfg_attr)) {
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
}
}
// Skip arguments that are configured out.
if ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(arg.attributes).is_none() {
if strip_unconfigured.configure(arg.attributes).is_none() {
continue;
}

View file

@ -60,6 +60,8 @@ declare_features! (
(accepted, adx_target_feature, "1.61.0", Some(44839)),
/// Allows explicit discriminants on non-unit enum variants.
(accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
/// Allows #[cfg(...)] on inline assembly templates and operands.
(accepted, asm_cfg, "CURRENT_RUSTC_VERSION", Some(140364)),
/// Allows using `const` operands in inline assembly.
(accepted, asm_const, "1.82.0", Some(93332)),
/// Allows using `label` operands in inline assembly.

View file

@ -382,8 +382,6 @@ declare_features! (
(unstable, arbitrary_self_types, "1.23.0", Some(44874)),
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
/// Allows #[cfg(...)] on inline assembly templates and operands.
(unstable, asm_cfg, "1.89.0", Some(140364)),
/// Enables experimental inline assembly support for additional architectures.
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
/// Enables experimental register support in inline assembly.

View file

@ -1186,14 +1186,21 @@ pub(crate) fn check_static_item<'tcx>(
) -> Result<(), ErrorGuaranteed> {
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
let span = tcx.ty_span(item_id);
let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
let loc = Some(WellFormedLoc::Ty(item_id));
let item_ty = wfcx.deeply_normalize(span, loc, ty);
let is_foreign_item = tcx.is_foreign_item(item_id);
let is_structurally_foreign_item = || {
let tail = tcx.struct_tail_raw(
item_ty,
&ObligationCause::dummy(),
|ty| wfcx.deeply_normalize(span, loc, ty),
|| {},
);
let forbid_unsized = !is_foreign_item || {
let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
!matches!(tail.kind(), ty::Foreign(_))
matches!(tail.kind(), ty::Foreign(_))
};
let forbid_unsized = !(is_foreign_item && is_structurally_foreign_item());
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {

View file

@ -666,99 +666,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn report_no_match_method_error(
fn suggest_method_call_annotation(
&self,
mut span: Span,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
expr_id: hir::HirId,
mode: Mode,
source: SelfSource<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
sugg_span: Span,
no_match_data: &mut NoMatchData<'tcx>,
expected: Expectation<'tcx>,
trait_missing_method: bool,
within_macro_span: Option<Span>,
) -> ErrorGuaranteed {
let mode = no_match_data.mode;
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
let mut ty_file = None;
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
let similar_candidate = no_match_data.similar_candidate;
let item_kind = if is_method {
"method"
} else if rcvr_ty.is_enum() {
"variant or associated item"
} else {
match (item_ident.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
(Some(name), false) if name.is_lowercase() => "function or associated item",
(Some(_), false) => "associated item",
(Some(_), true) | (None, false) => "variant or associated item",
(None, true) => "variant",
}
};
// We could pass the file for long types into these two, but it isn't strictly necessary
// given how targeted they are.
if let Err(guar) =
self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
{
return guar;
}
if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
tcx,
rcvr_ty,
source,
span,
item_kind,
item_ident,
&mut ty_file,
) {
return guar;
}
span = item_ident.span;
let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_ident.name == sym::write_fmt;
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
self.create_missing_writer_err(rcvr_ty, rcvr_expr, ty_file)
} else {
self.create_no_assoc_err(
rcvr_ty,
item_ident,
item_kind,
trait_missing_method,
source,
is_method,
sugg_span,
unsatisfied_predicates,
)
};
if rcvr_ty.references_error() {
err.downgrade_to_delayed_bug();
}
self.set_label_for_method_error(
&mut err,
source,
rcvr_ty,
item_ident,
expr_id,
span,
sugg_span,
within_macro_span,
args,
);
) {
if let Mode::MethodCall = mode
&& let SelfSource::MethodCall(cal) = source
{
self.suggest_await_before_method(
&mut err,
err,
item_ident,
rcvr_ty,
cal,
@ -767,10 +689,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
self.suggest_on_pointer_type(&mut err, source, rcvr_ty, item_ident);
self.suggest_on_pointer_type(err, source, rcvr_ty, item_ident);
if let SelfSource::MethodCall(rcvr_expr) = source {
self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
self.suggest_fn_call(err, rcvr_expr, rcvr_ty, |output_ty| {
let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
let probe = self.lookup_probe_for_diagnostic(
item_ident,
@ -782,14 +704,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
probe.is_ok()
});
self.note_internal_mutation_in_method(
&mut err,
err,
rcvr_expr,
expected.to_option(self),
rcvr_ty,
);
}
}
let mut custom_span_label = false;
fn suggest_static_method_candidates(
&self,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
source: SelfSource<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
sugg_span: Span,
no_match_data: &NoMatchData<'tcx>,
) -> Vec<CandidateSource> {
let mut static_candidates = no_match_data.static_candidates.clone();
// `static_candidates` may have same candidates appended by
@ -803,11 +736,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
functions must have a `self` parameter",
);
err.span_label(span, "this is an associated function, not a method");
custom_span_label = true;
}
if static_candidates.len() == 1 {
self.suggest_associated_call_syntax(
&mut err,
err,
&static_candidates,
rcvr_ty,
source,
@ -821,7 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source,
args,
span,
&mut err,
err,
&mut static_candidates,
None,
);
@ -832,23 +764,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source,
args,
span,
&mut err,
err,
&mut static_candidates,
Some(sugg_span),
);
}
static_candidates
}
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
fn suggest_unsatisfied_ty_or_trait(
&self,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
item_kind: &str,
source: SelfSource<'tcx>,
unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
static_candidates: &[CandidateSource],
) -> Result<(bool, bool, bool, bool, SortedMap<Span, Vec<String>>), ()> {
let mut restrict_type_params = false;
let mut suggested_derive = false;
let mut unsatisfied_bounds = false;
let mut ty_span = match rcvr_ty.kind() {
ty::Param(param_type) => {
Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
}
ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
_ => None,
};
let mut custom_span_label = !static_candidates.is_empty();
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
let tcx = self.tcx;
if item_ident.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
let msg = "consider using `len` instead";
@ -873,7 +813,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
}
return err.emit();
// Report to emit the diagnostic
return Err(());
} else if !unsatisfied_predicates.is_empty() {
if matches!(rcvr_ty.kind(), ty::Param(_)) {
// We special case the situation where we are looking for `_` in
@ -888,7 +829,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// suggestions.
} else {
self.handle_unsatisfied_predicates(
&mut err,
err,
rcvr_ty,
item_ident,
item_kind,
@ -936,21 +877,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
Ok((
restrict_type_params,
suggested_derive,
unsatisfied_bounds,
custom_span_label,
bound_spans,
))
}
let mut find_candidate_for_method = false;
let should_label_not_found = match source {
fn suggest_surround_method_call(
&self,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
source: SelfSource<'tcx>,
similar_candidate: &Option<ty::AssocItem>,
) -> bool {
match source {
// If the method name is the name of a field with a function or closure type,
// give a helping note that it has to be called as `(x.f)(...)`.
SelfSource::MethodCall(expr) => {
!self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_ident, &mut err)
!self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_ident, err)
&& similar_candidate.is_none()
}
_ => true,
};
}
}
fn find_possible_candidates_for_method(
&self,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
item_kind: &str,
mode: Mode,
source: SelfSource<'tcx>,
no_match_data: &NoMatchData<'tcx>,
expected: Expectation<'tcx>,
should_label_not_found: bool,
custom_span_label: bool,
) {
let mut find_candidate_for_method = false;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
if should_label_not_found && !custom_span_label {
self.set_not_found_span_label(
&mut err,
err,
rcvr_ty,
item_ident,
item_kind,
@ -963,7 +938,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if !find_candidate_for_method {
self.lookup_segments_chain_for_no_match_method(
&mut err,
err,
item_ident,
item_kind,
source,
@ -975,7 +950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// can't be called due to `typeof(expr): Clone` not holding.
if unsatisfied_predicates.is_empty() {
self.suggest_calling_method_on_field(
&mut err,
err,
source,
span,
rcvr_ty,
@ -983,37 +958,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected.only_has_type(self),
);
}
}
self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_ident);
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
// skip suggesting traits to import
} else {
self.suggest_traits_to_import(
&mut err,
span,
rcvr_ty,
item_ident,
args.map(|args| args.len() + 1),
source,
no_match_data.out_of_scope_traits.clone(),
&static_candidates,
unsatisfied_bounds,
expected.only_has_type(self),
trait_missing_method,
);
}
self.suggest_enum_variant_for_method_call(
&mut err,
rcvr_ty,
item_ident,
span,
source,
unsatisfied_predicates,
);
fn suggest_confusable_or_similarly_named_method(
&self,
err: &mut Diag<'_>,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
mode: Mode,
args: Option<&'tcx [hir::Expr<'tcx>]>,
unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
similar_candidate: Option<ty::AssocItem>,
) {
let confusable_suggested = self.confusable_method_name(
&mut err,
err,
rcvr_ty,
item_ident,
args.map(|args| {
@ -1033,18 +992,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// and if we aren't in an expansion.
&& !span.from_expansion()
{
self.find_likely_intended_associated_item(
&mut err,
similar_candidate,
span,
args,
mode,
);
self.find_likely_intended_associated_item(err, similar_candidate, span, args, mode);
}
}
}
fn suggest_method_not_found_because_of_unsatisfied_bounds(
&self,
err: &mut Diag<'_>,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
item_kind: &str,
bound_spans: SortedMap<Span, Vec<String>>,
) {
let mut ty_span = match rcvr_ty.kind() {
ty::Param(param_type) => {
Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
}
ty::Adt(def, _) if def.did().is_local() => Some(self.tcx.def_span(def.did())),
_ => None,
};
for (span, mut bounds) in bound_spans {
if !tcx.sess.source_map().is_span_accessible(span) {
if !self.tcx.sess.source_map().is_span_accessible(span) {
continue;
}
bounds.sort();
@ -1077,6 +1046,209 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
);
}
}
fn report_no_match_method_error(
&self,
span: Span,
rcvr_ty: Ty<'tcx>,
item_ident: Ident,
expr_id: hir::HirId,
source: SelfSource<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
sugg_span: Span,
no_match_data: &mut NoMatchData<'tcx>,
expected: Expectation<'tcx>,
trait_missing_method: bool,
within_macro_span: Option<Span>,
) -> ErrorGuaranteed {
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
if let Err(guar) = rcvr_ty.error_reported() {
return guar;
}
// We could pass the file for long types into these two, but it isn't strictly necessary
// given how targeted they are.
if let Err(guar) =
self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
{
return guar;
}
let mut ty_file = None;
let mode = no_match_data.mode;
let is_method = mode == Mode::MethodCall;
let item_kind = if is_method {
"method"
} else if rcvr_ty.is_enum() {
"variant or associated item"
} else {
match (item_ident.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
(Some(name), false) if name.is_lowercase() => "function or associated item",
(Some(_), false) => "associated item",
(Some(_), true) | (None, false) => "variant or associated item",
(None, true) => "variant",
}
};
if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
tcx,
rcvr_ty,
source,
span,
item_kind,
item_ident,
&mut ty_file,
) {
return guar;
}
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_ident.name == sym::write_fmt;
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
self.create_missing_writer_err(rcvr_ty, rcvr_expr, ty_file)
} else {
self.create_no_assoc_err(
rcvr_ty,
item_ident,
item_kind,
trait_missing_method,
source,
is_method,
sugg_span,
unsatisfied_predicates,
)
};
self.set_label_for_method_error(
&mut err,
source,
rcvr_ty,
item_ident,
expr_id,
item_ident.span,
sugg_span,
within_macro_span,
args,
);
self.suggest_method_call_annotation(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
mode,
source,
expected,
);
let static_candidates = self.suggest_static_method_candidates(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
source,
args,
sugg_span,
&no_match_data,
);
let Ok((
restrict_type_params,
suggested_derive,
unsatisfied_bounds,
custom_span_label,
bound_spans,
)) = self.suggest_unsatisfied_ty_or_trait(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
item_kind,
source,
unsatisfied_predicates,
&static_candidates,
)
else {
return err.emit();
};
let similar_candidate = no_match_data.similar_candidate;
let should_label_not_found = self.suggest_surround_method_call(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
source,
&similar_candidate,
);
self.find_possible_candidates_for_method(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
item_kind,
mode,
source,
no_match_data,
expected,
should_label_not_found,
custom_span_label,
);
self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_ident);
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
// skip suggesting traits to import
} else {
self.suggest_traits_to_import(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
args.map(|args| args.len() + 1),
source,
no_match_data.out_of_scope_traits.clone(),
&static_candidates,
unsatisfied_bounds,
expected.only_has_type(self),
trait_missing_method,
);
}
self.suggest_enum_variant_for_method_call(
&mut err,
rcvr_ty,
item_ident,
item_ident.span,
source,
unsatisfied_predicates,
);
self.suggest_confusable_or_similarly_named_method(
&mut err,
item_ident.span,
rcvr_ty,
item_ident,
mode,
args,
unsatisfied_predicates,
similar_candidate,
);
self.suggest_method_not_found_because_of_unsatisfied_bounds(
&mut err,
rcvr_ty,
item_ident,
item_kind,
bound_spans,
);
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected);
self.suggest_bounds_for_range_to_method(&mut err, source, item_ident);

View file

@ -74,7 +74,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
}
// delete comparison statement if it the value being switched on was moved, which means
// it can not be user later on
// it can not be used later on
if opt.can_remove_bin_op_stmt {
bb.statements[opt.bin_op_stmt_idx].make_nop(true);
} else {

View file

@ -74,6 +74,8 @@ where
/// Consider a clause specifically for a `dyn Trait` self type. This requires
/// additionally checking all of the supertraits and object bounds to hold,
/// since they're not implied by the well-formedness of the object type.
/// `NormalizesTo` overrides this to not check the supertraits for backwards
/// compatibility with the old solver. cc trait-system-refactor-initiative#245.
fn probe_and_consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, D>,
source: CandidateSource<I>,

View file

@ -184,6 +184,20 @@ where
then(ecx)
}
// Hack for trait-system-refactor-initiative#245.
// FIXME(-Zhigher-ranked-assumptions): this impl differs from trait goals and we should unify
// them again once we properly support binders.
fn probe_and_consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, D>,
source: CandidateSource<I>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<Candidate<I>, NoSolution> {
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
fn consider_additional_alias_assumptions(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,

View file

@ -882,11 +882,11 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
DefPathData::OpaqueTy => 'i',
DefPathData::SyntheticCoroutineBody => 's',
DefPathData::NestedStatic => 'n',
DefPathData::GlobalAsm => 'a',
// These should never show up as `print_path_with_simple` arguments.
DefPathData::CrateRoot
| DefPathData::Use
| DefPathData::GlobalAsm
| DefPathData::Impl
| DefPathData::MacroNs(_)
| DefPathData::LifetimeNs(_)

View file

@ -7,7 +7,6 @@
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(linkage)]
#![feature(asm_cfg)]
#![feature(naked_functions)]
#![feature(repr_simd)]
#![feature(macro_metavar_expr_concat)]

View file

@ -376,14 +376,10 @@ impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
impl<T: Clone> Clone for OnceCell<T> {
#[inline]
fn clone(&self) -> OnceCell<T> {
let res = OnceCell::new();
if let Some(value) = self.get() {
match res.set(value.clone()) {
Ok(()) => (),
Err(_) => unreachable!(),
}
match self.get() {
Some(value) => OnceCell::from(value.clone()),
None => OnceCell::new(),
}
res
}
}

View file

@ -2020,13 +2020,11 @@ fn render_impl(
let mut methods = Vec::new();
if !impl_.is_negative_trait_impl() {
for trait_item in &impl_.items {
match trait_item.kind {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
methods.push(trait_item)
}
for impl_item in &impl_.items {
match impl_item.kind {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => methods.push(impl_item),
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => {
assoc_types.push(trait_item)
assoc_types.push(impl_item)
}
clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(_)
@ -2036,7 +2034,7 @@ fn render_impl(
&mut default_impl_items,
&mut impl_items,
cx,
trait_item,
impl_item,
if trait_.is_some() { &i.impl_item } else { parent },
link,
render_mode,

View file

@ -582,18 +582,14 @@ impl TypeAliasPart {
if let Some(ret) = &mut ret {
ret.aliases.push(type_alias_fqp);
} else {
let target_did = impl_
.inner_impl()
.trait_
.as_ref()
.map(|trait_| trait_.def_id())
.or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
let target_trait_did =
impl_.inner_impl().trait_.as_ref().map(|trait_| trait_.def_id());
let provided_methods;
let assoc_link = if let Some(target_did) = target_did {
let assoc_link = if let Some(target_trait_did) = target_trait_did {
provided_methods =
impl_.inner_impl().provided_trait_methods(cx.tcx());
AssocItemLink::GotoSource(
ItemId::DefId(target_did),
ItemId::DefId(target_trait_did),
&provided_methods,
)
} else {

View file

@ -786,3 +786,13 @@ pub mod tooltips {
Vec::new()
}
}
pub mod tyalias {
pub struct X<T>(pub T);
impl<T: std::fmt::Debug> X<T> {
pub fn blob(&self) {}
}
pub type Y = X<u8>;
}

View file

@ -0,0 +1,7 @@
// This test ensures that we correctly generate links to methods on type aliases.
go-to: "file://" + |DOC_PATH| + "/test_docs/tyalias/type.Y.html"
// It's generated with JS so we need to wait for it to be done generating.
wait-for: "#implementations"
// We check that it's "#method." and not "#tymethod.".
assert-text: ('#method\.blob a.fn[href="#method.blob"]', "blob")

View file

@ -1,5 +1,4 @@
//@ needs-asm-support
#![feature(asm_cfg)]
use std::arch::asm;

View file

@ -1,5 +1,5 @@
error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
--> $DIR/cfg-parse-error.rs:16:13
--> $DIR/cfg-parse-error.rs:15:13
|
LL | a = out(reg) x,
| - expected one of 11 possible tokens
@ -7,7 +7,7 @@ LL | "",
| ^^ unexpected token
error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
--> $DIR/cfg-parse-error.rs:26:13
--> $DIR/cfg-parse-error.rs:25:13
|
LL | },
| - expected one of 11 possible tokens
@ -15,19 +15,19 @@ LL | "",
| ^^ unexpected token
error: expected token: `,`
--> $DIR/cfg-parse-error.rs:41:26
--> $DIR/cfg-parse-error.rs:40:26
|
LL | a = out(reg) x,
| ^ expected `,`
error: this attribute is not supported on assembly
--> $DIR/cfg-parse-error.rs:47:13
--> $DIR/cfg-parse-error.rs:46:13
|
LL | #[rustfmt::skip]
| ^^^^^^^^^^^^^^^^
error: an inner attribute is not permitted in this context
--> $DIR/cfg-parse-error.rs:53:13
--> $DIR/cfg-parse-error.rs:52:13
|
LL | #![rustfmt::skip]
| ^^^^^^^^^^^^^^^^^

View file

@ -3,7 +3,7 @@
//@ revisions: reva revb
//@ only-x86_64
//@ run-pass
#![feature(asm_cfg, cfg_select)]
#![feature(cfg_select)]
use std::arch::{asm, naked_asm};

View file

@ -1,48 +0,0 @@
//@ only-x86_64
#![crate_type = "lib"]
use std::arch::{asm, global_asm, naked_asm};
global_asm!(
"nop",
#[cfg(false)]
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
"nop"
);
#[unsafe(naked)]
#[no_mangle]
extern "C" fn naked() {
naked_asm!(
"mov rax, 5",
#[cfg(false)]
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
"mov rax, {a}",
"ret",
#[cfg(false)]
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
a = const 10,
)
}
fn asm() {
unsafe {
asm!(
"nop",
#[cfg(false)]
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
clobber_abi("C"),
clobber_abi("C"), //~ ERROR `C` ABI specified multiple times
);
}
}
fn bad_attribute() {
unsafe {
asm!(
#[inline]
//~^ ERROR this attribute is not supported on assembly
"nop"
)
};
}

View file

@ -1,57 +0,0 @@
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
--> $DIR/feature-gate-asm_cfg.rs:8:5
|
LL | #[cfg(false)]
| ^^^^^^^^^^^^^
|
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
--> $DIR/feature-gate-asm_cfg.rs:18:9
|
LL | #[cfg(false)]
| ^^^^^^^^^^^^^
|
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
--> $DIR/feature-gate-asm_cfg.rs:22:9
|
LL | #[cfg(false)]
| ^^^^^^^^^^^^^
|
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
--> $DIR/feature-gate-asm_cfg.rs:32:13
|
LL | #[cfg(false)]
| ^^^^^^^^^^^^^
|
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: this attribute is not supported on assembly
--> $DIR/feature-gate-asm_cfg.rs:43:13
|
LL | #[inline]
| ^^^^^^^^^
error: `C` ABI specified multiple times
--> $DIR/feature-gate-asm_cfg.rs:35:13
|
LL | clobber_abi("C"),
| ---------------- previously specified here
LL | clobber_abi("C"),
| ^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,21 @@
// Regression test for https://github.com/rust-lang/rust/issues/148161
trait Trait {
type Assoc;
}
impl Trait for u8 {
type Assoc = i8;
}
struct Struct<T: Trait> {
member: T::Assoc,
}
unsafe extern "C" {
// This used to be an ICE due to normalization failure on `<Struct<i8> as Trait>::Assoc`
// while wf checking this static item.
static VAR: Struct<i8>;
//~^ ERROR: the trait bound `i8: Trait` is not satisfied
}
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0277]: the trait bound `i8: Trait` is not satisfied
--> $DIR/extern-static-normalization-failure-issue-148161.rs:17:17
|
LL | static VAR: Struct<i8>;
| ^^^^^^^^^^ the trait `Trait` is not implemented for `i8`
|
help: the trait `Trait` is implemented for `u8`
--> $DIR/extern-static-normalization-failure-issue-148161.rs:6:1
|
LL | impl Trait for u8 {
| ^^^^^^^^^^^^^^^^^
note: required by a bound in `Struct`
--> $DIR/extern-static-normalization-failure-issue-148161.rs:10:18
|
LL | struct Struct<T: Trait> {
| ^^^^^ required by this bound in `Struct`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,20 @@
//@ build-pass
//@ compile-flags: -Clink-dead-code
//@ needs-asm-support
#![allow(unused)]
// Test that a symbol in a `global_asm` namespace doesn't cause an ICE during v0 symbol mangling
// due to a lack of missing namespace character for `global_asm`.
//
// FIXME: Can't use `#[rustc_symbol_name]` on the `foo` call to check its symbol, so just checking
// the test compiles.
fn foo<const N: usize>() {}
core::arch::global_asm!("/* {} */", sym foo::<{
|| {};
0
}>);
fn main() {}

View file

@ -0,0 +1,39 @@
//@ check-pass
//@ compile-flags: -Znext-solver
//@ edition: 2024
// A regression test for trait-system-refactor-initiative#245.
// The old solver doesn't check the supertraits of the principal trait
// when considering object candidate for normalization.
// And the new solver previously did, resulting in a placeholder error
// while normalizing inside of a generator witness.
trait AsyncFn: Send + 'static {
type Fut: Future<Output = ()> + Send;
fn call(&self) -> Self::Fut;
}
type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
fn wrap_call<P: AsyncFn + ?Sized>(func: Box<P>) -> impl Future<Output = ()> {
func.call()
}
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
todo!()
}
async fn cursed_fut() {
wrap_call(get_boxed_fn()).await;
}
fn observe_fut_not_send() {
fn assert_send<T: Send>(t: T) -> T {
t
}
assert_send(cursed_fut());
}
fn main() {}