Auto merge of #106034 - matthiaskrgr:rollup-2zpql33, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #104741 (Switch `#[track_caller]` back to a no-op unless feature gate is enabled) - #105769 (add function to tell the identical errors for ambiguity_errors) - #105843 (Suggest associated const on possible capitalization mistake) - #105966 (Re-enable `Fn` trait call notation error for non-tuple argument) - #106002 (codegen tests: adapt patterns to also work with v0 symbol mangling) - #106010 (Give opaque types a better coherence error) - #106016 (rustdoc: simplify link anchor to section expand JS) - #106024 (Fix ICE due to `todo!()` in `rustdoc` for `Term`s) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2d8651a927
28 changed files with 424 additions and 136 deletions
|
@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir::ExprKind::Closure(c)
|
hir::ExprKind::Closure(c)
|
||||||
};
|
};
|
||||||
|
|
||||||
let track_caller = self
|
|
||||||
.attrs
|
|
||||||
.get(&outer_hir_id.local_id)
|
|
||||||
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
|
|
||||||
|
|
||||||
let hir_id = self.lower_node_id(closure_node_id);
|
let hir_id = self.lower_node_id(closure_node_id);
|
||||||
if track_caller {
|
let unstable_span =
|
||||||
let unstable_span = self.mark_span_with_reason(
|
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||||
DesugaringKind::Async,
|
|
||||||
span,
|
if self.tcx.features().closure_track_caller
|
||||||
self.allow_gen_future.clone(),
|
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
||||||
);
|
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
|
||||||
|
{
|
||||||
self.lower_attrs(
|
self.lower_attrs(
|
||||||
hir_id,
|
hir_id,
|
||||||
&[Attribute {
|
&[Attribute {
|
||||||
|
|
|
@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes =
|
||||||
|
|
||||||
lint_builtin_unstable_features = unstable feature
|
lint_builtin_unstable_features = unstable feature
|
||||||
|
|
||||||
|
lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
|
||||||
|
.label = this function will not propagate the caller location
|
||||||
|
|
||||||
lint_builtin_unreachable_pub = unreachable `pub` {$what}
|
lint_builtin_unreachable_pub = unreachable `pub` {$what}
|
||||||
.suggestion = consider restricting its visibility
|
.suggestion = consider restricting its visibility
|
||||||
.help = or consider exporting it for use by other crates
|
.help = or consider exporting it for use by other crates
|
||||||
|
|
|
@ -184,11 +184,19 @@ fn emit_orphan_check_error<'tcx>(
|
||||||
ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
|
ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
|
||||||
_ => ty,
|
_ => ty,
|
||||||
};
|
};
|
||||||
let this = "this".to_string();
|
let msg = |ty: &str, postfix: &str| {
|
||||||
let (ty, postfix) = match &ty.kind() {
|
format!("{ty} is not defined in the current crate{postfix}")
|
||||||
ty::Slice(_) => (this, " because slices are always foreign"),
|
};
|
||||||
ty::Array(..) => (this, " because arrays are always foreign"),
|
let this = |name: &str| msg("this", &format!(" because {name} are always foreign"));
|
||||||
ty::Tuple(..) => (this, " because tuples are always foreign"),
|
let msg = match &ty.kind() {
|
||||||
|
ty::Slice(_) => this("slices"),
|
||||||
|
ty::Array(..) => this("arrays"),
|
||||||
|
ty::Tuple(..) => this("tuples"),
|
||||||
|
ty::Alias(ty::Opaque, ..) => {
|
||||||
|
"type alias impl trait is treated as if it were foreign, \
|
||||||
|
because its hidden type could be from a foreign crate"
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
ty::RawPtr(ptr_ty) => {
|
ty::RawPtr(ptr_ty) => {
|
||||||
emit_newtype_suggestion_for_raw_ptr(
|
emit_newtype_suggestion_for_raw_ptr(
|
||||||
full_impl_span,
|
full_impl_span,
|
||||||
|
@ -198,12 +206,11 @@ fn emit_orphan_check_error<'tcx>(
|
||||||
&mut err,
|
&mut err,
|
||||||
);
|
);
|
||||||
|
|
||||||
(format!("`{}`", ty), " because raw pointers are always foreign")
|
msg(&format!("`{ty}`"), " because raw pointers are always foreign")
|
||||||
}
|
}
|
||||||
_ => (format!("`{}`", ty), ""),
|
_ => msg(&format!("`{ty}`"), ""),
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = format!("{} is not defined in the current crate{}", ty, postfix);
|
|
||||||
if is_target_ty {
|
if is_target_ty {
|
||||||
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
|
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
|
||||||
err.span_label(self_ty_span, &msg);
|
err.span_label(self_ty_span, &msg);
|
||||||
|
|
|
@ -23,6 +23,35 @@ use std::cmp::min;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
pub fn emit_type_mismatch_suggestions(
|
||||||
|
&self,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
expr: &hir::Expr<'tcx>,
|
||||||
|
expr_ty: Ty<'tcx>,
|
||||||
|
expected: Ty<'tcx>,
|
||||||
|
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||||
|
_error: Option<TypeError<'tcx>>,
|
||||||
|
) {
|
||||||
|
if expr_ty == expected {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use `||` to give these suggestions a precedence
|
||||||
|
let _ = self.suggest_missing_parentheses(err, expr)
|
||||||
|
|| self.suggest_associated_const(err, expr, expected)
|
||||||
|
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
|
||||||
|
|| self.suggest_option_to_bool(err, expr, expr_ty, expected)
|
||||||
|
|| self.suggest_compatible_variants(err, expr, expected, expr_ty)
|
||||||
|
|| self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
|
||||||
|
|| self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
|
||||||
|
|| self.suggest_no_capture_closure(err, expected, expr_ty)
|
||||||
|
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|
||||||
|
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
||||||
|
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
||||||
|
|| self.suggest_into(err, expr, expr_ty, expected)
|
||||||
|
|| self.suggest_floating_point_literal(err, expr, expected);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn emit_coerce_suggestions(
|
pub fn emit_coerce_suggestions(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -37,21 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.annotate_expected_due_to_let_ty(err, expr, error);
|
self.annotate_expected_due_to_let_ty(err, expr, error);
|
||||||
|
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
|
||||||
// Use `||` to give these suggestions a precedence
|
|
||||||
let _ = self.suggest_missing_parentheses(err, expr)
|
|
||||||
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
|
|
||||||
|| self.suggest_compatible_variants(err, expr, expected, expr_ty)
|
|
||||||
|| self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
|
|
||||||
|| self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
|
|
||||||
|| self.suggest_no_capture_closure(err, expected, expr_ty)
|
|
||||||
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|
|
||||||
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
|
||||||
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
|
||||||
|| self.suggest_into(err, expr, expr_ty, expected)
|
|
||||||
|| self.suggest_option_to_bool(err, expr, expr_ty, expected)
|
|
||||||
|| self.suggest_floating_point_literal(err, expr, expected);
|
|
||||||
|
|
||||||
self.note_type_is_not_clone(err, expected, expr_ty, expr);
|
self.note_type_is_not_clone(err, expected, expr_ty, expr);
|
||||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||||
|
|
|
@ -104,16 +104,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||||
// FIXME(compiler-errors): We probably should fold some of the
|
let _ = self.emit_type_mismatch_suggestions(
|
||||||
// `suggest_` functions from `emit_coerce_suggestions` into here,
|
|
||||||
// since some of those aren't necessarily just coerce suggestions.
|
|
||||||
let _ = self.suggest_deref_ref_or_into(
|
|
||||||
&mut err,
|
&mut err,
|
||||||
expr.peel_drop_temps(),
|
expr.peel_drop_temps(),
|
||||||
expected_ty,
|
|
||||||
ty,
|
ty,
|
||||||
|
expected_ty,
|
||||||
None,
|
None,
|
||||||
) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty);
|
None,
|
||||||
|
);
|
||||||
extend_err(&mut err);
|
extend_err(&mut err);
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"cannot use call notation; the first type parameter \
|
"cannot use call notation; the first type parameter \
|
||||||
for the function trait is neither a tuple nor unit"
|
for the function trait is neither a tuple nor unit"
|
||||||
)
|
)
|
||||||
.delay_as_bug();
|
.emit();
|
||||||
(self.err_args(provided_args.len()), None)
|
(self.err_args(provided_args.len()), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
|
|
||||||
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
|
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
|
||||||
|
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
|
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
|
||||||
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
|
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -15,10 +16,11 @@ use rustc_infer::traits::{self, StatementAsExpression};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
|
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
|
||||||
|
TypeVisitable,
|
||||||
};
|
};
|
||||||
use rustc_session::errors::ExprParenthesesNeeded;
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::{Span, Symbol};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
|
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||||
|
@ -1236,6 +1238,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn suggest_associated_const(
|
||||||
|
&self,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
expr: &hir::Expr<'_>,
|
||||||
|
expected_ty: Ty<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
let Some((DefKind::AssocFn, old_def_id)) = self.typeck_results.borrow().type_dependent_def(expr.hir_id) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let old_item_name = self.tcx.item_name(old_def_id);
|
||||||
|
let capitalized_name = Symbol::intern(&old_item_name.as_str().to_uppercase());
|
||||||
|
if old_item_name == capitalized_name {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let (item, segment) = match expr.kind {
|
||||||
|
hir::ExprKind::Path(QPath::Resolved(
|
||||||
|
Some(ty),
|
||||||
|
hir::Path { segments: [segment], .. },
|
||||||
|
))
|
||||||
|
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
|
||||||
|
let self_ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
|
||||||
|
if let Ok(pick) = self.probe_for_name(
|
||||||
|
Mode::Path,
|
||||||
|
Ident::new(capitalized_name, segment.ident.span),
|
||||||
|
IsSuggestion(true),
|
||||||
|
self_ty,
|
||||||
|
expr.hir_id,
|
||||||
|
ProbeScope::TraitsInScope,
|
||||||
|
) {
|
||||||
|
(pick.item, segment)
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hir::ExprKind::Path(QPath::Resolved(
|
||||||
|
None,
|
||||||
|
hir::Path { segments: [.., segment], .. },
|
||||||
|
)) => {
|
||||||
|
// we resolved through some path that doesn't end in the item name,
|
||||||
|
// better not do a bad suggestion by accident.
|
||||||
|
if old_item_name != segment.ident.name {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Some(item) = self
|
||||||
|
.tcx
|
||||||
|
.associated_items(self.tcx.parent(old_def_id))
|
||||||
|
.filter_by_name_unhygienic(capitalized_name)
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
(*item, segment)
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
if item.def_id == old_def_id || self.tcx.def_kind(item.def_id) != DefKind::AssocConst {
|
||||||
|
// Same item
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let item_ty = self.tcx.type_of(item.def_id);
|
||||||
|
// FIXME(compiler-errors): This check is *so* rudimentary
|
||||||
|
if item_ty.needs_subst() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if self.can_coerce(item_ty, expected_ty) {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
segment.ident.span,
|
||||||
|
format!("try referring to the associated const `{capitalized_name}` instead",),
|
||||||
|
capitalized_name,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_loop(&self, id: hir::HirId) -> bool {
|
fn is_loop(&self, id: hir::HirId) -> bool {
|
||||||
let node = self.tcx.hir().get(id);
|
let node = self.tcx.hir().get(id);
|
||||||
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
|
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::{
|
||||||
types::{transparent_newtype_field, CItemKind},
|
types::{transparent_newtype_field, CItemKind},
|
||||||
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
|
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
|
||||||
};
|
};
|
||||||
|
use hir::IsAsync;
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||||
use rustc_ast::visit::{FnCtxt, FnKind};
|
use rustc_ast::visit::{FnCtxt, FnKind};
|
||||||
|
@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
|
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
|
||||||
use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin};
|
use rustc_hir::intravisit::FnKind as HirFnKind;
|
||||||
|
use rustc_hir::{
|
||||||
|
Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
|
||||||
|
};
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
|
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
|
||||||
|
@ -1370,6 +1374,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `ungated_async_fn_track_caller` lint warns when the
|
||||||
|
/// `#[track_caller]` attribute is used on an async function, method, or
|
||||||
|
/// closure, without enabling the corresponding unstable feature flag.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// #[track_caller]
|
||||||
|
/// async fn foo() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// The attribute must be used in conjunction with the
|
||||||
|
/// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
|
||||||
|
/// annotation will function as as no-op.
|
||||||
|
///
|
||||||
|
/// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
|
||||||
|
UNGATED_ASYNC_FN_TRACK_CALLER,
|
||||||
|
Warn,
|
||||||
|
"enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(
|
||||||
|
/// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
|
||||||
|
/// do anything
|
||||||
|
UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
|
||||||
|
fn check_fn(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'_>,
|
||||||
|
fn_kind: HirFnKind<'_>,
|
||||||
|
_: &'tcx FnDecl<'_>,
|
||||||
|
_: &'tcx Body<'_>,
|
||||||
|
span: Span,
|
||||||
|
hir_id: HirId,
|
||||||
|
) {
|
||||||
|
if fn_kind.asyncness() == IsAsync::Async
|
||||||
|
&& !cx.tcx.features().closure_track_caller
|
||||||
|
&& let attrs = cx.tcx.hir().attrs(hir_id)
|
||||||
|
// Now, check if the function has the `#[track_caller]` attribute
|
||||||
|
&& let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
|
||||||
|
{
|
||||||
|
cx.struct_span_lint(
|
||||||
|
UNGATED_ASYNC_FN_TRACK_CALLER,
|
||||||
|
attr.span,
|
||||||
|
fluent::lint_ungated_async_fn_track_caller,
|
||||||
|
|lint| {
|
||||||
|
lint.span_label(span, fluent::label);
|
||||||
|
rustc_session::parse::add_feature_diagnostics(
|
||||||
|
lint,
|
||||||
|
&cx.tcx.sess.parse_sess,
|
||||||
|
sym::closure_track_caller,
|
||||||
|
);
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
|
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
|
||||||
/// the crate root.
|
/// the crate root.
|
||||||
|
|
|
@ -219,6 +219,7 @@ late_lint_methods!(
|
||||||
// May Depend on constants elsewhere
|
// May Depend on constants elsewhere
|
||||||
UnusedBrokenConst: UnusedBrokenConst,
|
UnusedBrokenConst: UnusedBrokenConst,
|
||||||
UnstableFeatures: UnstableFeatures,
|
UnstableFeatures: UnstableFeatures,
|
||||||
|
UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
|
||||||
ArrayIntoIter: ArrayIntoIter::default(),
|
ArrayIntoIter: ArrayIntoIter::default(),
|
||||||
DropTraitConstraints: DropTraitConstraints,
|
DropTraitConstraints: DropTraitConstraints,
|
||||||
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
|
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
|
||||||
|
|
|
@ -1686,6 +1686,24 @@ impl<'a> Resolver<'a> {
|
||||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test if AmbiguityError ambi is any identical to any one inside ambiguity_errors
|
||||||
|
fn matches_previous_ambiguity_error(&mut self, ambi: &AmbiguityError<'_>) -> bool {
|
||||||
|
for ambiguity_error in &self.ambiguity_errors {
|
||||||
|
// if the span location and ident as well as its span are the same
|
||||||
|
if ambiguity_error.kind == ambi.kind
|
||||||
|
&& ambiguity_error.ident == ambi.ident
|
||||||
|
&& ambiguity_error.ident.span == ambi.ident.span
|
||||||
|
&& ambiguity_error.b1.span == ambi.b1.span
|
||||||
|
&& ambiguity_error.b2.span == ambi.b2.span
|
||||||
|
&& ambiguity_error.misc1 == ambi.misc1
|
||||||
|
&& ambiguity_error.misc2 == ambi.misc2
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn record_use(
|
fn record_use(
|
||||||
&mut self,
|
&mut self,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
|
@ -1693,14 +1711,18 @@ impl<'a> Resolver<'a> {
|
||||||
is_lexical_scope: bool,
|
is_lexical_scope: bool,
|
||||||
) {
|
) {
|
||||||
if let Some((b2, kind)) = used_binding.ambiguity {
|
if let Some((b2, kind)) = used_binding.ambiguity {
|
||||||
self.ambiguity_errors.push(AmbiguityError {
|
let ambiguity_error = AmbiguityError {
|
||||||
kind,
|
kind,
|
||||||
ident,
|
ident,
|
||||||
b1: used_binding,
|
b1: used_binding,
|
||||||
b2,
|
b2,
|
||||||
misc1: AmbiguityErrorMisc::None,
|
misc1: AmbiguityErrorMisc::None,
|
||||||
misc2: AmbiguityErrorMisc::None,
|
misc2: AmbiguityErrorMisc::None,
|
||||||
});
|
};
|
||||||
|
if !self.matches_previous_ambiguity_error(&ambiguity_error) {
|
||||||
|
// avoid dumplicated span information to be emitt out
|
||||||
|
self.ambiguity_errors.push(ambiguity_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
|
if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
|
||||||
// Avoid marking `extern crate` items that refer to a name from extern prelude,
|
// Avoid marking `extern crate` items that refer to a name from extern prelude,
|
||||||
|
|
|
@ -1655,10 +1655,10 @@ impl clean::types::Term {
|
||||||
&'a self,
|
&'a self,
|
||||||
cx: &'a Context<'tcx>,
|
cx: &'a Context<'tcx>,
|
||||||
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
||||||
match self {
|
display_fn(move |f| match self {
|
||||||
clean::types::Term::Type(ty) => ty.print(cx),
|
clean::types::Term::Type(ty) => fmt::Display::fmt(&ty.print(cx), f),
|
||||||
_ => todo!(),
|
clean::types::Term::Constant(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -813,16 +813,14 @@ function loadCss(cssUrl) {
|
||||||
hideSidebar();
|
hideSidebar();
|
||||||
});
|
});
|
||||||
|
|
||||||
onEachLazy(document.getElementsByTagName("a"), el => {
|
onEachLazy(document.querySelectorAll("a[href^='#']"), el => {
|
||||||
// For clicks on internal links (<A> tags with a hash property), we expand the section we're
|
// For clicks on internal links (<A> tags with a hash property), we expand the section we're
|
||||||
// jumping to *before* jumping there. We can't do this in onHashChange, because it changes
|
// jumping to *before* jumping there. We can't do this in onHashChange, because it changes
|
||||||
// the height of the document so we wind up scrolled to the wrong place.
|
// the height of the document so we wind up scrolled to the wrong place.
|
||||||
if (el.hash) {
|
el.addEventListener("click", () => {
|
||||||
el.addEventListener("click", () => {
|
expandSection(el.hash.slice(1));
|
||||||
expandSection(el.hash.slice(1));
|
hideSidebar();
|
||||||
hideSidebar();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => {
|
onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => {
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]]
|
// CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() {
|
pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() {
|
||||||
// CHECK: call void @_ZN4core9panicking15panic_no_unwind
|
// Handle both legacy and v0 symbol mangling.
|
||||||
|
// CHECK: call void @{{.*core9panicking15panic_no_unwind}}
|
||||||
may_unwind();
|
may_unwind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ extern "C-unwind" {
|
||||||
|
|
||||||
// CHECK: Function Attrs:{{.*}}nounwind
|
// CHECK: Function Attrs:{{.*}}nounwind
|
||||||
// CHECK-NEXT: define{{.*}}void @foo
|
// CHECK-NEXT: define{{.*}}void @foo
|
||||||
// CHECK: call void @_ZN4core9panicking15panic_no_unwind
|
// Handle both legacy and v0 symbol mangling.
|
||||||
|
// CHECK: call void @{{.*core9panicking15panic_no_unwind}}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn foo() {
|
pub unsafe extern "C" fn foo() {
|
||||||
bar();
|
bar();
|
||||||
|
|
14
src/test/rustdoc/issue-105952.rs
Normal file
14
src/test/rustdoc/issue-105952.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
#![feature(associated_const_equality)]
|
||||||
|
pub enum ParseMode {
|
||||||
|
Raw,
|
||||||
|
}
|
||||||
|
pub trait Parse {
|
||||||
|
const PARSE_MODE: ParseMode;
|
||||||
|
}
|
||||||
|
pub trait RenderRaw {}
|
||||||
|
|
||||||
|
// @hasraw foo/trait.RenderRaw.html 'impl'
|
||||||
|
// @hasraw foo/trait.RenderRaw.html 'ParseMode::Raw'
|
||||||
|
impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}
|
|
@ -5,6 +5,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = #[track_caller] async || {
|
let _ = #[track_caller] async || {
|
||||||
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
|
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
|
||||||
//~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,19 +7,6 @@ LL | let _ = #[track_caller] async || {
|
||||||
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
|
||||||
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: `#[track_caller]` on closures is currently unstable
|
error: aborting due to previous error
|
||||||
--> $DIR/async-closure-gate.rs:6:38
|
|
||||||
|
|
|
||||||
LL | let _ = #[track_caller] async || {
|
|
||||||
| ______________________________________^
|
|
||||||
LL | |
|
|
||||||
LL | |
|
|
||||||
LL | | };
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
|
|
||||||
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
warning: `#[track_caller]` on async functions is a no-op
|
||||||
|
--> $DIR/panic-track-caller.rs:50:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
LL | / async fn bar_track_caller() {
|
||||||
|
LL | | panic!()
|
||||||
|
LL | | }
|
||||||
|
| |_- this function will not propagate the caller location
|
||||||
|
|
|
||||||
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
|
||||||
|
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
||||||
|
= note: `#[warn(ungated_async_fn_track_caller)]` on by default
|
||||||
|
|
||||||
|
warning: `#[track_caller]` on async functions is a no-op
|
||||||
|
--> $DIR/panic-track-caller.rs:62:5
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
LL | / async fn bar_assoc() {
|
||||||
|
LL | | panic!();
|
||||||
|
LL | | }
|
||||||
|
| |_____- this function will not propagate the caller location
|
||||||
|
|
|
||||||
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
|
||||||
|
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
warning: 2 warnings emitted
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
// edition:2021
|
// edition:2021
|
||||||
|
// revisions: feat nofeat
|
||||||
// needs-unwind
|
// needs-unwind
|
||||||
#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
|
#![feature(async_closure, stmt_expr_attributes)]
|
||||||
|
#![cfg_attr(feat, feature(closure_track_caller))]
|
||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::panic;
|
use std::panic;
|
||||||
|
@ -45,7 +47,7 @@ async fn foo() {
|
||||||
bar().await
|
bar().await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
|
||||||
async fn bar_track_caller() {
|
async fn bar_track_caller() {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
@ -57,7 +59,7 @@ async fn foo_track_caller() {
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
#[track_caller]
|
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
|
||||||
async fn bar_assoc() {
|
async fn bar_assoc() {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
@ -67,6 +69,9 @@ async fn foo_assoc() {
|
||||||
Foo::bar_assoc().await
|
Foo::bar_assoc().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since compilation is expected to fail for this fn when using
|
||||||
|
// `nofeat`, we test that separately in `async-closure-gate.rs`
|
||||||
|
#[cfg(feat)]
|
||||||
async fn foo_closure() {
|
async fn foo_closure() {
|
||||||
let c = #[track_caller] async || {
|
let c = #[track_caller] async || {
|
||||||
panic!();
|
panic!();
|
||||||
|
@ -91,8 +96,18 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(panicked_at(|| block_on(foo())), 41);
|
assert_eq!(panicked_at(|| block_on(foo())), 43);
|
||||||
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
|
|
||||||
assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
|
#[cfg(feat)]
|
||||||
assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
|
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56);
|
||||||
|
#[cfg(nofeat)]
|
||||||
|
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52);
|
||||||
|
|
||||||
|
#[cfg(feat)]
|
||||||
|
assert_eq!(panicked_at(|| block_on(foo_assoc())), 69);
|
||||||
|
#[cfg(nofeat)]
|
||||||
|
assert_eq!(panicked_at(|| block_on(foo_assoc())), 64);
|
||||||
|
|
||||||
|
#[cfg(feat)]
|
||||||
|
assert_eq!(panicked_at(|| block_on(foo_closure())), 79);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ mod inner1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
exported!(); //~ ERROR `exported` is ambiguous
|
exported!(); //~ ERROR `exported` is ambiguous
|
||||||
//~| ERROR `exported` is ambiguous
|
|
||||||
|
|
||||||
mod inner2 {
|
mod inner2 {
|
||||||
define_exported!();
|
define_exported!();
|
||||||
|
|
|
@ -23,33 +23,8 @@ LL | use inner1::*;
|
||||||
= help: consider adding an explicit import of `exported` to disambiguate
|
= help: consider adding an explicit import of `exported` to disambiguate
|
||||||
= note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0659]: `exported` is ambiguous
|
|
||||||
--> $DIR/local-modularized-tricky-fail-1.rs:28:1
|
|
||||||
|
|
|
||||||
LL | exported!();
|
|
||||||
| ^^^^^^^^ ambiguous name
|
|
||||||
|
|
|
||||||
= note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
|
|
||||||
note: `exported` could refer to the macro defined here
|
|
||||||
--> $DIR/local-modularized-tricky-fail-1.rs:5:5
|
|
||||||
|
|
|
||||||
LL | / macro_rules! exported {
|
|
||||||
LL | | () => ()
|
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
...
|
|
||||||
LL | define_exported!();
|
|
||||||
| ------------------ in this macro invocation
|
|
||||||
note: `exported` could also refer to the macro imported here
|
|
||||||
--> $DIR/local-modularized-tricky-fail-1.rs:22:5
|
|
||||||
|
|
|
||||||
LL | use inner1::*;
|
|
||||||
| ^^^^^^^^^
|
|
||||||
= help: consider adding an explicit import of `exported` to disambiguate
|
|
||||||
= note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0659]: `panic` is ambiguous
|
error[E0659]: `panic` is ambiguous
|
||||||
--> $DIR/local-modularized-tricky-fail-1.rs:36:5
|
--> $DIR/local-modularized-tricky-fail-1.rs:35:5
|
||||||
|
|
|
|
||||||
LL | panic!();
|
LL | panic!();
|
||||||
| ^^^^^ ambiguous name
|
| ^^^^^ ambiguous name
|
||||||
|
@ -70,7 +45,7 @@ LL | define_panic!();
|
||||||
= note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0659]: `include` is ambiguous
|
error[E0659]: `include` is ambiguous
|
||||||
--> $DIR/local-modularized-tricky-fail-1.rs:47:1
|
--> $DIR/local-modularized-tricky-fail-1.rs:46:1
|
||||||
|
|
|
|
||||||
LL | include!();
|
LL | include!();
|
||||||
| ^^^^^^^ ambiguous name
|
| ^^^^^^^ ambiguous name
|
||||||
|
@ -90,6 +65,6 @@ LL | define_include!();
|
||||||
= help: use `crate::include` to refer to this macro unambiguously
|
= help: use `crate::include` to refer to this macro unambiguously
|
||||||
= note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0659`.
|
For more information about this error, try `rustc --explain E0659`.
|
||||||
|
|
|
@ -14,7 +14,6 @@ mod m1 {
|
||||||
mod m2 {
|
mod m2 {
|
||||||
use two_macros::*;
|
use two_macros::*;
|
||||||
m! { //~ ERROR ambiguous
|
m! { //~ ERROR ambiguous
|
||||||
//~| ERROR ambiguous
|
|
||||||
use foo::m;
|
use foo::m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ LL | m! {
|
||||||
|
|
|
|
||||||
= note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
|
= note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
|
||||||
note: `m` could refer to the macro imported here
|
note: `m` could refer to the macro imported here
|
||||||
--> $DIR/macros.rs:18:13
|
--> $DIR/macros.rs:17:13
|
||||||
|
|
|
|
||||||
LL | use foo::m;
|
LL | use foo::m;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -18,43 +18,24 @@ LL | use two_macros::*;
|
||||||
= help: consider adding an explicit import of `m` to disambiguate
|
= help: consider adding an explicit import of `m` to disambiguate
|
||||||
|
|
||||||
error[E0659]: `m` is ambiguous
|
error[E0659]: `m` is ambiguous
|
||||||
--> $DIR/macros.rs:16:5
|
--> $DIR/macros.rs:29:9
|
||||||
|
|
|
||||||
LL | m! {
|
|
||||||
| ^ ambiguous name
|
|
||||||
|
|
|
||||||
= note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
|
|
||||||
note: `m` could refer to the macro imported here
|
|
||||||
--> $DIR/macros.rs:18:13
|
|
||||||
|
|
|
||||||
LL | use foo::m;
|
|
||||||
| ^^^^^^
|
|
||||||
note: `m` could also refer to the macro imported here
|
|
||||||
--> $DIR/macros.rs:15:9
|
|
||||||
|
|
|
||||||
LL | use two_macros::*;
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
= help: consider adding an explicit import of `m` to disambiguate
|
|
||||||
|
|
||||||
error[E0659]: `m` is ambiguous
|
|
||||||
--> $DIR/macros.rs:30:9
|
|
||||||
|
|
|
|
||||||
LL | m! {
|
LL | m! {
|
||||||
| ^ ambiguous name
|
| ^ ambiguous name
|
||||||
|
|
|
|
||||||
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
|
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
|
||||||
note: `m` could refer to the macro imported here
|
note: `m` could refer to the macro imported here
|
||||||
--> $DIR/macros.rs:31:17
|
--> $DIR/macros.rs:30:17
|
||||||
|
|
|
|
||||||
LL | use two_macros::n as m;
|
LL | use two_macros::n as m;
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
note: `m` could also refer to the macro imported here
|
note: `m` could also refer to the macro imported here
|
||||||
--> $DIR/macros.rs:23:9
|
--> $DIR/macros.rs:22:9
|
||||||
|
|
|
|
||||||
LL | use two_macros::m;
|
LL | use two_macros::m;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= help: use `self::m` to refer to this macro unambiguously
|
= help: use `self::m` to refer to this macro unambiguously
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0659`.
|
For more information about this error, try `rustc --explain E0659`.
|
||||||
|
|
25
src/test/ui/suggestions/assoc-ct-for-assoc-method.rs
Normal file
25
src/test/ui/suggestions/assoc-ct-for-assoc-method.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
struct MyS;
|
||||||
|
|
||||||
|
impl MyS {
|
||||||
|
const FOO: i32 = 1;
|
||||||
|
fn foo() -> MyS {
|
||||||
|
MyS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: i32 = MyS::foo;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
//~| HELP try referring to the
|
||||||
|
|
||||||
|
let z: i32 = i32::max;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
//~| HELP try referring to the
|
||||||
|
|
||||||
|
// This example is still broken though... This is a hard suggestion to make,
|
||||||
|
// because we don't have access to the associated const probing code to make
|
||||||
|
// this suggestion where it's emitted, i.e. in trait selection.
|
||||||
|
let y: i32 = i32::max - 42;
|
||||||
|
//~^ ERROR cannot subtract
|
||||||
|
//~| HELP use parentheses
|
||||||
|
}
|
47
src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr
Normal file
47
src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/assoc-ct-for-assoc-method.rs:11:18
|
||||||
|
|
|
||||||
|
LL | let x: i32 = MyS::foo;
|
||||||
|
| --- ^^^^^^^^ expected `i32`, found fn item
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found fn item `fn() -> MyS {MyS::foo}`
|
||||||
|
help: try referring to the associated const `FOO` instead
|
||||||
|
|
|
||||||
|
LL | let x: i32 = MyS::FOO;
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/assoc-ct-for-assoc-method.rs:15:18
|
||||||
|
|
|
||||||
|
LL | let z: i32 = i32::max;
|
||||||
|
| --- ^^^^^^^^ expected `i32`, found fn item
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found fn item `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
|
||||||
|
help: try referring to the associated const `MAX` instead
|
||||||
|
|
|
||||||
|
LL | let z: i32 = i32::MAX;
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error[E0369]: cannot subtract `{integer}` from `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
|
||||||
|
--> $DIR/assoc-ct-for-assoc-method.rs:22:27
|
||||||
|
|
|
||||||
|
LL | let y: i32 = i32::max - 42;
|
||||||
|
| -------- ^ -- {integer}
|
||||||
|
| |
|
||||||
|
| fn(i32, i32) -> i32 {<i32 as Ord>::max}
|
||||||
|
|
|
||||||
|
help: use parentheses to call this associated function
|
||||||
|
|
|
||||||
|
LL | let y: i32 = i32::max(/* i32 */, /* i32 */) - 42;
|
||||||
|
| ++++++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0308, E0369.
|
||||||
|
For more information about an error, try `rustc --explain E0308`.
|
|
@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
|
||||||
LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
|
LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
|
||||||
| | |
|
| | |
|
||||||
| | `AliasOfForeignType<T>` is not defined in the current crate
|
| | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
|
||||||
| impl doesn't use only types from inside the current crate
|
| impl doesn't use only types from inside the current crate
|
||||||
|
|
|
|
||||||
= note: define and implement a trait or new type instead
|
= note: define and implement a trait or new type instead
|
||||||
|
|
17
src/test/ui/unboxed-closures/non-tupled-call.rs
Normal file
17
src/test/ui/unboxed-closures/non-tupled-call.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#![feature(fn_traits, unboxed_closures, tuple_trait)]
|
||||||
|
|
||||||
|
use std::default::Default;
|
||||||
|
use std::marker::Tuple;
|
||||||
|
|
||||||
|
fn wrap<P: Tuple + Default, T>(func: impl Fn<P, Output = T>) {
|
||||||
|
let x: P = Default::default();
|
||||||
|
// Should be: `func.call(x);`
|
||||||
|
func(x);
|
||||||
|
//~^ ERROR cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
wrap(foo);
|
||||||
|
}
|
9
src/test/ui/unboxed-closures/non-tupled-call.stderr
Normal file
9
src/test/ui/unboxed-closures/non-tupled-call.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
|
||||||
|
--> $DIR/non-tupled-call.rs:9:5
|
||||||
|
|
|
||||||
|
LL | func(x);
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0059`.
|
Loading…
Add table
Add a link
Reference in a new issue