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:
commit
80d8f292d8
25 changed files with 488 additions and 305 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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(_)
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
|||
7
tests/rustdoc-gui/type-alias.goml
Normal file
7
tests/rustdoc-gui/type-alias.goml
Normal 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")
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
//@ needs-asm-support
|
||||
#![feature(asm_cfg)]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
20
tests/ui/symbol-names/const-in-global-asm.rs
Normal file
20
tests/ui/symbol-names/const-in-global-asm.rs
Normal 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() {}
|
||||
|
|
@ -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() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue