diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a3f5c18f2e7..3634e6e47ce 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> { 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); - if track_caller { - let unstable_span = self.mark_span_with_reason( - DesugaringKind::Async, - span, - self.allow_gen_future.clone(), - ); + let unstable_span = + self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + + if self.tcx.features().closure_track_caller + && 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( hir_id, &[Attribute { diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 7e28f22c0ba..2eb409a5ddd 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes = 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} .suggestion = consider restricting its visibility .help = or consider exporting it for use by other crates diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index cc5114dba5e..c6d4aeefc80 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -184,11 +184,19 @@ fn emit_orphan_check_error<'tcx>( ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()), _ => ty, }; - let this = "this".to_string(); - let (ty, postfix) = match &ty.kind() { - ty::Slice(_) => (this, " because slices are always foreign"), - ty::Array(..) => (this, " because arrays are always foreign"), - ty::Tuple(..) => (this, " because tuples are always foreign"), + let msg = |ty: &str, postfix: &str| { + format!("{ty} is not defined in the current crate{postfix}") + }; + let this = |name: &str| msg("this", &format!(" because {name} 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) => { emit_newtype_suggestion_for_raw_ptr( full_impl_span, @@ -198,12 +206,11 @@ fn emit_orphan_check_error<'tcx>( &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 { // Point at `D` in `impl for C in D` err.span_label(self_ty_span, &msg); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 479aaf2e1a7..e68bd1297c8 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -23,6 +23,35 @@ use std::cmp::min; use std::iter; 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>, + ) { + 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( &self, err: &mut Diagnostic, @@ -37,21 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.annotate_expected_due_to_let_ty(err, 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.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error); self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index edbbb7272ac..ae641b26eee 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -104,16 +104,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - // FIXME(compiler-errors): We probably should fold some of the - // `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( + let _ = self.emit_type_mismatch_suggestions( &mut err, expr.peel_drop_temps(), - expected_ty, ty, + expected_ty, None, - ) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty); + None, + ); extend_err(&mut err); err.emit(); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d1e0964112b..877680053f0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) - .delay_as_bug(); + .emit(); (self.err_args(provided_args.len()), None) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c9d179de39f..efec0244633 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1,6 +1,7 @@ use super::FnCtxt; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; +use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_errors::{Applicability, Diagnostic, MultiSpan}; 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::ty::{ self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty, + TypeVisitable, }; use rustc_session::errors::ExprParenthesesNeeded; -use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::symbol::{sym, Ident}; +use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::DefIdOrName; 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 = >::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 { let node = self.tcx.hir().get(id); matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index cd19e65b6fc..d6de6e70ead 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -25,6 +25,7 @@ use crate::{ types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, }; +use hir::IsAsync; use rustc_ast::attr; use rustc_ast::tokenstream::{TokenStream, TokenTree}; 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::def::{DefKind, Res}; 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_middle::lint::in_external_macro; 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! { /// The `unreachable_pub` lint triggers for `pub` items not reachable from /// the crate root. diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 11022eb80ea..1275d6f223c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -219,6 +219,7 @@ late_lint_methods!( // May Depend on constants elsewhere UnusedBrokenConst: UnusedBrokenConst, UnstableFeatures: UnstableFeatures, + UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller, ArrayIntoIter: ArrayIntoIter::default(), DropTraitConstraints: DropTraitConstraints, TemporaryCStringAsPtr: TemporaryCStringAsPtr, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4861ee746aa..2182b736937 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1686,6 +1686,24 @@ impl<'a> Resolver<'a> { .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( &mut self, ident: Ident, @@ -1693,14 +1711,18 @@ impl<'a> Resolver<'a> { is_lexical_scope: bool, ) { if let Some((b2, kind)) = used_binding.ambiguity { - self.ambiguity_errors.push(AmbiguityError { + let ambiguity_error = AmbiguityError { kind, ident, b1: used_binding, b2, misc1: 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 { // Avoid marking `extern crate` items that refer to a name from extern prelude, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 39e2a902226..5ad24bf2681 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1655,10 +1655,10 @@ impl clean::types::Term { &'a self, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - match self { - clean::types::Term::Type(ty) => ty.print(cx), - _ => todo!(), - } + display_fn(move |f| match self { + clean::types::Term::Type(ty) => fmt::Display::fmt(&ty.print(cx), f), + clean::types::Term::Constant(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f), + }) } } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 3f97e4e2e39..60e4e749224 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -813,16 +813,14 @@ function loadCss(cssUrl) { hideSidebar(); }); - onEachLazy(document.getElementsByTagName("a"), el => { + onEachLazy(document.querySelectorAll("a[href^='#']"), el => { // For clicks on internal links ( 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 // the height of the document so we wind up scrolled to the wrong place. - if (el.hash) { - el.addEventListener("click", () => { - expandSection(el.hash.slice(1)); - hideSidebar(); - }); - } + el.addEventListener("click", () => { + expandSection(el.hash.slice(1)); + hideSidebar(); + }); }); onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => { diff --git a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs index 8447bbeb1ed..34fd401f9e4 100644 --- a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs +++ b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs @@ -9,7 +9,8 @@ // CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]] #[no_mangle] 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(); } diff --git a/src/test/codegen/unwind-and-panic-abort.rs b/src/test/codegen/unwind-and-panic-abort.rs index f238741e599..b370191bf8c 100644 --- a/src/test/codegen/unwind-and-panic-abort.rs +++ b/src/test/codegen/unwind-and-panic-abort.rs @@ -9,7 +9,8 @@ extern "C-unwind" { // CHECK: Function Attrs:{{.*}}nounwind // 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] pub unsafe extern "C" fn foo() { bar(); diff --git a/src/test/rustdoc/issue-105952.rs b/src/test/rustdoc/issue-105952.rs new file mode 100644 index 00000000000..e3f1df0063d --- /dev/null +++ b/src/test/rustdoc/issue-105952.rs @@ -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> RenderRaw for T {} diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.rs b/src/test/ui/async-await/track-caller/async-closure-gate.rs index 9593fdb1908..d9d55685599 100644 --- a/src/test/ui/async-await/track-caller/async-closure-gate.rs +++ b/src/test/ui/async-await/track-caller/async-closure-gate.rs @@ -5,6 +5,5 @@ fn main() { let _ = #[track_caller] async || { //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658] - //~| ERROR `#[track_caller]` on closures is currently unstable [E0658] }; } diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.stderr b/src/test/ui/async-await/track-caller/async-closure-gate.stderr index be3d110eccd..498f1b43b9b 100644 --- a/src/test/ui/async-await/track-caller/async-closure-gate.stderr +++ b/src/test/ui/async-await/track-caller/async-closure-gate.stderr @@ -7,19 +7,6 @@ LL | let _ = #[track_caller] async || { = note: see issue #87417 for more information = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable -error[E0658]: `#[track_caller]` on closures is currently unstable - --> $DIR/async-closure-gate.rs:6:38 - | -LL | let _ = #[track_caller] async || { - | ______________________________________^ -LL | | -LL | | -LL | | }; - | |_____^ - | - = note: see issue #87417 for more information - = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr new file mode 100644 index 00000000000..51ea225f4cb --- /dev/null +++ b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr @@ -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 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 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +warning: 2 warnings emitted + diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs index 066cf97628f..f45243b0ea6 100644 --- a/src/test/ui/async-await/track-caller/panic-track-caller.rs +++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs @@ -1,7 +1,9 @@ // run-pass // edition:2021 +// revisions: feat nofeat // 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::panic; @@ -45,7 +47,7 @@ async fn foo() { bar().await } -#[track_caller] +#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op async fn bar_track_caller() { panic!() } @@ -57,7 +59,7 @@ async fn foo_track_caller() { struct Foo; impl Foo { - #[track_caller] + #[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op async fn bar_assoc() { panic!(); } @@ -67,6 +69,9 @@ async fn foo_assoc() { 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() { let c = #[track_caller] async || { panic!(); @@ -91,8 +96,18 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { } fn main() { - assert_eq!(panicked_at(|| block_on(foo())), 41); - assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54); - assert_eq!(panicked_at(|| block_on(foo_assoc())), 67); - assert_eq!(panicked_at(|| block_on(foo_closure())), 74); + assert_eq!(panicked_at(|| block_on(foo())), 43); + + #[cfg(feat)] + 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); } diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs index 37fe0eceed6..29e9b8ec841 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs @@ -26,7 +26,6 @@ mod inner1 { } exported!(); //~ ERROR `exported` is ambiguous - //~| ERROR `exported` is ambiguous mod inner2 { define_exported!(); diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index c048d2ea204..20eadaaaa56 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -23,33 +23,8 @@ 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]: `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 - --> $DIR/local-modularized-tricky-fail-1.rs:36:5 + --> $DIR/local-modularized-tricky-fail-1.rs:35:5 | LL | panic!(); | ^^^^^ 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) 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!(); | ^^^^^^^ ambiguous name @@ -90,6 +65,6 @@ LL | define_include!(); = 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) -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs index f39711898cd..f2a22ad620b 100644 --- a/src/test/ui/imports/macros.rs +++ b/src/test/ui/imports/macros.rs @@ -14,7 +14,6 @@ mod m1 { mod m2 { use two_macros::*; m! { //~ ERROR ambiguous - //~| ERROR ambiguous use foo::m; } } diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index 110548d1d6a..e34e5359b48 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -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: `m` could refer to the macro imported here - --> $DIR/macros.rs:18:13 + --> $DIR/macros.rs:17:13 | LL | use foo::m; | ^^^^^^ @@ -18,43 +18,24 @@ LL | use two_macros::*; = help: consider adding an explicit import of `m` to disambiguate error[E0659]: `m` is ambiguous - --> $DIR/macros.rs:16:5 - | -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 + --> $DIR/macros.rs:29:9 | LL | m! { | ^ 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: `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; | ^^^^^^^^^^^^^^^^^^ 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; | ^^^^^^^^^^^^^ = 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`. diff --git a/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs b/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs new file mode 100644 index 00000000000..fe222776989 --- /dev/null +++ b/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs @@ -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 +} diff --git a/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr b/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr new file mode 100644 index 00000000000..afef38f1296 --- /dev/null +++ b/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr @@ -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 {::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 {::max}` + --> $DIR/assoc-ct-for-assoc-method.rs:22:27 + | +LL | let y: i32 = i32::max - 42; + | -------- ^ -- {integer} + | | + | fn(i32, i32) -> i32 {::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`. diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr index c923eb08ab3..00b0dbbb583 100644 --- a/src/test/ui/type-alias-impl-trait/coherence.stderr +++ b/src/test/ui/type-alias-impl-trait/coherence.stderr @@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar LL | impl foreign_crate::ForeignTrait for AliasOfForeignType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- | | | - | | `AliasOfForeignType` 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 | = note: define and implement a trait or new type instead diff --git a/src/test/ui/unboxed-closures/non-tupled-call.rs b/src/test/ui/unboxed-closures/non-tupled-call.rs new file mode 100644 index 00000000000..08bea4f1678 --- /dev/null +++ b/src/test/ui/unboxed-closures/non-tupled-call.rs @@ -0,0 +1,17 @@ +#![feature(fn_traits, unboxed_closures, tuple_trait)] + +use std::default::Default; +use std::marker::Tuple; + +fn wrap(func: impl Fn) { + 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); +} diff --git a/src/test/ui/unboxed-closures/non-tupled-call.stderr b/src/test/ui/unboxed-closures/non-tupled-call.stderr new file mode 100644 index 00000000000..35ac9ebe291 --- /dev/null +++ b/src/test/ui/unboxed-closures/non-tupled-call.stderr @@ -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`.