diff options
137 files changed, 1590 insertions, 1001 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 68f1637e07e..f1320048533 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -417,7 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// minimum values. /// /// For example: - /// ``` + /// ```ignore (illustrative) /// fn foo<'a, 'b>( /* ... */ ) where 'a: 'b { /* ... */ } /// ``` /// would initialize two variables like so: diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 99392ea1915..eb31b5de05d 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -86,7 +86,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // them with fresh ty vars. resume_ty: next_ty_var(), yield_ty: next_ty_var(), - witness: next_ty_var(), }, ) .args, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 0517fd0419d..f02aa6c120f 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1411,9 +1411,8 @@ impl InvocationCollectorNode for P<ast::Item> { } } } - let mut idents = Vec::new(); - collect_use_tree_leaves(ut, &mut idents); + collect_use_tree_leaves(&ut, &mut idents); idents } else { self.kind.ident().into_iter().collect() diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 3fee9af01b3..2201d493f2d 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -360,7 +360,7 @@ impl DefKind { /// For example, everything prefixed with `/* Res */` in this example has /// an associated `Res`: /// -/// ``` +/// ```ignore (illustrative) /// fn str_to_string(s: & /* Res */ str) -> /* Res */ String { /// /* Res */ String::from(/* Res */ s) /// } @@ -421,7 +421,7 @@ pub enum Res<Id = hir::HirId> { /// } /// /// impl Foo for Bar { - /// fn foo() -> Box<Self> { // SelfTyAlias + /// fn foo() -> Box<Self /* SelfTyAlias */> { /// let _: Self; // SelfTyAlias /// /// todo!() diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1b1b3ced44d..08361718108 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3016,7 +3016,7 @@ impl fmt::Display for LoopIdError { } } -#[derive(Copy, Clone, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)] pub struct Destination { /// This is `Some(_)` iff there is an explicit user-specified 'label pub label: Option<Label>, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e24426f9fed..bd9125363fc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -425,7 +425,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> { /// /// trait Foo { /// fn bar() -> impl Deref<Target = impl Sized>; -/// // ^- RPITIT #1 ^- RPITIT #2 +/// // ^- RPITIT #1 ^- RPITIT #2 /// } /// /// impl Foo for () { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 31e9c3b80fb..e2462c2d465 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -379,20 +379,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["<closure_kind>", "<closure_signature>", "<upvars>"][..], - ClosureKind::Coroutine(_) => &[ - "<coroutine_kind>", - "<resume_ty>", - "<yield_ty>", - "<return_ty>", - "<witness>", - "<upvars>", - ][..], + ClosureKind::Coroutine(_) => { + &["<coroutine_kind>", "<resume_ty>", "<yield_ty>", "<return_ty>", "<upvars>"][..] + } ClosureKind::CoroutineClosure(_) => &[ "<closure_kind>", "<closure_signature_parts>", "<upvars>", "<bound_captures_by_ref>", - "<witness>", ][..], }; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a413f805873..82b7c578a1f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -161,8 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resume type defaults to `()` if the coroutine has no argument. let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); - let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args); - // Coroutines that come from coroutine closures have not yet determined // their kind ty, so make a fresh infer var which will be constrained // later during upvar analysis. Regular coroutines always have the kind @@ -182,7 +180,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { resume_ty, yield_ty, return_ty: liberated_sig.output(), - witness: interior, tupled_upvars_ty, }, ); @@ -210,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Compute all of the variables that will be used to populate the coroutine. let resume_ty = self.next_ty_var(expr_span); - let interior = self.next_ty_var(expr_span); let closure_kind_ty = match expected_kind { Some(kind) => Ty::from_closure_kind(tcx, kind), @@ -243,7 +239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty: interior, }, ); diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index d47a3246964..acfa5c473aa 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -2,7 +2,6 @@ use std::collections::BTreeMap; use std::fmt; use Context::*; -use rustc_ast::Label; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; @@ -42,8 +41,8 @@ enum Context { ConstBlock, /// E.g. `#[loop_match] loop { state = 'label: { /* ... */ } }`. LoopMatch { - /// The label of the labeled block (not of the loop itself). - labeled_block: Label, + /// The destination pointing to the labeled block (not to the loop itself). + labeled_block: Destination, }, } @@ -186,18 +185,18 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { { self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b)); } - hir::ExprKind::Break(break_label, ref opt_expr) => { + hir::ExprKind::Break(break_destination, ref opt_expr) => { if let Some(e) = opt_expr { self.visit_expr(e); } - if self.require_label_in_labeled_block(e.span, &break_label, "break") { + if self.require_label_in_labeled_block(e.span, &break_destination, "break") { // If we emitted an error about an unlabeled break in a labeled // block, we don't need any further checking for this break any more return; } - let loop_id = match break_label.target_id { + let loop_id = match break_destination.target_id { Ok(loop_id) => Some(loop_id), Err(hir::LoopIdError::OutsideLoopScope) => None, Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { @@ -212,18 +211,25 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { // A `#[const_continue]` must break to a block in a `#[loop_match]`. if find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::ConstContinue(_)) { - if let Some(break_label) = break_label.label { - let is_target_label = |cx: &Context| match cx { - Context::LoopMatch { labeled_block } => { - break_label.ident.name == labeled_block.ident.name - } - _ => false, - }; + let Some(label) = break_destination.label else { + let span = e.span; + self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); + }; - if !self.cx_stack.iter().rev().any(is_target_label) { - let span = break_label.ident.span; - self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); + let is_target_label = |cx: &Context| match cx { + Context::LoopMatch { labeled_block } => { + // NOTE: with macro expansion, the label's span might be different here + // even though it does still refer to the same HIR node. A block + // can't have two labels, so the hir_id is a unique identifier. + assert!(labeled_block.target_id.is_ok()); // see `is_loop_match`. + break_destination.target_id == labeled_block.target_id } + _ => false, + }; + + if !self.cx_stack.iter().rev().any(is_target_label) { + let span = label.ident.span; + self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); } } @@ -249,7 +255,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { Some(kind) => { let suggestion = format!( "break{}", - break_label + break_destination .label .map_or_else(String::new, |l| format!(" {}", l.ident)) ); @@ -259,7 +265,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { kind: kind.name(), suggestion, loop_label, - break_label: break_label.label, + break_label: break_destination.label, break_expr_kind: &break_expr.kind, break_expr_span: break_expr.span, }); @@ -268,7 +274,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { } let sp_lo = e.span.with_lo(e.span.lo() + BytePos("break".len() as u32)); - let label_sp = match break_label.label { + let label_sp = match break_destination.label { Some(label) => sp_lo.with_hi(label.ident.span.hi()), None => sp_lo.shrink_to_lo(), }; @@ -416,7 +422,7 @@ impl<'hir> CheckLoopVisitor<'hir> { &self, e: &'hir hir::Expr<'hir>, body: &'hir hir::Block<'hir>, - ) -> Option<Label> { + ) -> Option<Destination> { if !find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::LoopMatch(_)) { return None; } @@ -438,8 +444,8 @@ impl<'hir> CheckLoopVisitor<'hir> { let hir::ExprKind::Assign(_, rhs_expr, _) = loop_body_expr.kind else { return None }; - let hir::ExprKind::Block(_, label) = rhs_expr.kind else { return None }; + let hir::ExprKind::Block(block, label) = rhs_expr.kind else { return None }; - label + Some(Destination { label, target_id: Ok(block.hir_id) }) } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index df38c3a1214..50fa3f2cc9d 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -2391,13 +2391,11 @@ fn migration_suggestion_for_2229( /// let mut p = Point { x: 10, y: 10 }; /// /// let c = || { -/// p.x += 10; -/// // ^ E1 ^ +/// p.x += 10; // E1 /// // ... /// // More code /// // ... /// p.x += 10; // E2 -/// // ^ E2 ^ /// }; /// ``` /// `CaptureKind` associated with both `E1` and `E2` will be ByRef(MutBorrow), diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index bb3b51c0ab2..b989d419057 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -36,7 +36,7 @@ //! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T)) {} //! fn foo<T>(x: T) { //! bar(x, |y| { /* ... */}) -//! // ^ closure arg +//! // ^ closure arg //! } //! ``` //! diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 83ac981429c..8dec8069bc7 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1151,7 +1151,9 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { parallel!( { - tcx.ensure_ok().check_private_in_public(()); + tcx.par_hir_for_each_module(|module| { + tcx.ensure_ok().check_private_in_public(module) + }) }, { tcx.par_hir_for_each_module(|module| { diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 3683d1e251c..4370816d38e 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -533,8 +533,10 @@ impl<'tcx> TyCtxt<'tcx> { /// ``` /// fn foo(x: usize) -> bool { /// if x == 1 { - /// true // If `get_fn_id_for_return_block` gets passed the `id` corresponding - /// } else { // to this, it will return `foo`'s `HirId`. + /// // If `get_fn_id_for_return_block` gets passed the `id` corresponding to this, it + /// // will return `foo`'s `HirId`. + /// true + /// } else { /// false /// } /// } @@ -543,8 +545,10 @@ impl<'tcx> TyCtxt<'tcx> { /// ```compile_fail,E0308 /// fn foo(x: usize) -> bool { /// loop { - /// true // If `get_fn_id_for_return_block` gets passed the `id` corresponding - /// } // to this, it will return `None`. + /// // If `get_fn_id_for_return_block` gets passed the `id` corresponding to this, it + /// // will return `None`. + /// true + /// } /// false /// } /// ``` diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e819aa2d8f8..c55c7fc6002 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1017,7 +1017,8 @@ pub struct LocalDecl<'tcx> { /// ``` /// fn foo(x: &str) { /// #[allow(unused_mut)] - /// let mut x: u32 = { // <- one unused mut + /// let mut x: u32 = { + /// //^ one unused mut /// let mut y: u32 = x.parse().unwrap(); /// y + 2 /// }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b02433d2feb..2941808e806 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1390,8 +1390,11 @@ rustc_queries! { eval_always desc { "checking effective visibilities" } } - query check_private_in_public(_: ()) { - desc { "checking for private elements in public interfaces" } + query check_private_in_public(module_def_id: LocalModDefId) { + desc { |tcx| + "checking for private elements in public interfaces for {}", + describe_as_module(module_def_id, tcx) + } } query reachable_set(_: ()) -> &'tcx LocalDefIdSet { diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 7d34d8df3f3..b02abb5ab43 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -96,14 +96,12 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg signature_parts_ty, tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty, ] => ty::CoroutineClosureArgsParts { parent_args, closure_kind_ty: closure_kind_ty.expect_ty(), signature_parts_ty: signature_parts_ty.expect_ty(), tupled_upvars_ty: tupled_upvars_ty.expect_ty(), coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), - coroutine_witness_ty: coroutine_witness_ty.expect_ty(), }, _ => bug!("closure args missing synthetics"), } @@ -111,23 +109,16 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg fn split_coroutine_args(self) -> ty::CoroutineArgsParts<TyCtxt<'tcx>> { match self[..] { - [ - ref parent_args @ .., - kind_ty, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, - ] => ty::CoroutineArgsParts { - parent_args, - kind_ty: kind_ty.expect_ty(), - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - }, + [ref parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => { + ty::CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + } + } _ => bug!("coroutine args missing synthetics"), } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5c44b10ba71..71eac294f15 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -913,9 +913,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " yield_ty=", print(args.as_coroutine().yield_ty()), " return_ty=", - print(args.as_coroutine().return_ty()), - " witness=", - print(args.as_coroutine().witness()) + print(args.as_coroutine().return_ty()) ); } @@ -1035,9 +1033,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " upvar_tys=", print(args.as_coroutine_closure().tupled_upvars_ty()), " coroutine_captures_by_ref_ty=", - print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), - " coroutine_witness_ty=", - print(args.as_coroutine_closure().coroutine_witness_ty()) + print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()) ); } p!("}}"); diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index abfe8eb66dd..287639de663 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -87,7 +87,7 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]` .label = this value is too generic -mir_build_const_continue_missing_value = a `#[const_continue]` must break to a label with a value +mir_build_const_continue_missing_label_or_value = a `#[const_continue]` must break to a label with a value mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]` .help = try extracting the expression into a `const` item diff --git a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs index 982e7aa8246..6a422223990 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs @@ -57,7 +57,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// ``` /// #![feature(unsized_fn_params)] /// # use core::fmt::Debug; - /// fn foo(_p: dyn Debug) { /* ... */ } + /// fn foo(_p: dyn Debug) { + /// /* ... */ + /// } /// /// fn bar(box_p: Box<dyn Debug>) { foo(*box_p); } /// ``` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f1fbd5c4a49..1a52c6c85cb 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1254,8 +1254,8 @@ pub(crate) struct ConstContinueBadConst { } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_missing_value)] -pub(crate) struct ConstContinueMissingValue { +#[diag(mir_build_const_continue_missing_label_or_value)] +pub(crate) struct ConstContinueMissingLabelOrValue { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index a0d3913c159..81b0e21a5f5 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -852,9 +852,9 @@ impl<'tcx> ThirBuildCx<'tcx> { if find_attr!(self.tcx.hir_attrs(expr.hir_id), AttributeKind::ConstContinue(_)) { match dest.target_id { Ok(target_id) => { - let Some(value) = value else { + let (Some(value), Some(_)) = (value, dest.label) else { let span = expr.span; - self.tcx.dcx().emit_fatal(ConstContinueMissingValue { span }) + self.tcx.dcx().emit_fatal(ConstContinueMissingLabelOrValue { span }) }; ExprKind::ConstContinue { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 117525eb777..5937d68f389 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -108,6 +108,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> { /// /// ```rust /// struct S; +/// #[rustfmt::skip] /// fn foo(pred: bool) { // maybe-init: /// // {} /// let a = S; let mut b = S; let c; let d; // {a, b} @@ -197,6 +198,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { /// /// ```rust /// struct S; +/// #[rustfmt::skip] /// fn foo(pred: bool) { // maybe-uninit: /// // {a, b, c, d} /// let a = S; let mut b = S; let c; let d; // { c, d} @@ -289,6 +291,7 @@ impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { /// /// ```rust /// struct S; +/// #[rustfmt::skip] /// fn foo(pred: bool) { // ever-init: /// // { } /// let a = S; let mut b = S; let c; let d; // {a, b } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index df4853c1dcb..4f3c53d761f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -611,6 +611,7 @@ where /// /// For example, with 3 fields, the drop ladder is /// + /// ```text /// .d0: /// ELAB(drop location.0 [target=.d1, unwind=.c1]) /// .d1: @@ -621,8 +622,10 @@ where /// ELAB(drop location.1 [target=.c2]) /// .c2: /// ELAB(drop location.2 [target=`self.unwind`]) + /// ``` /// /// For possible-async drops in coroutines we also need dropline ladder + /// ```text /// .d0 (mainline): /// ELAB(drop location.0 [target=.d1, unwind=.c1, drop=.e1]) /// .d1 (mainline): @@ -637,6 +640,7 @@ where /// ELAB(drop location.1 [target=.e2, unwind=.c2]) /// .e2 (dropline): /// ELAB(drop location.2 [target=`self.drop`, unwind=`self.unwind`]) + /// ``` /// /// NOTE: this does not clear the master drop flag, so you need /// to point succ/unwind on a `drop_ladder_bottom`. diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index c0bebdf6fb6..faa86734d08 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -75,9 +75,16 @@ where Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()])) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let coroutine_args = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine_args.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine_args.parent_args().as_slice()), + ), + ])) } ty::CoroutineWitness(def_id, args) => Ok(ecx @@ -245,7 +252,14 @@ where Movability::Movable => { if ecx.cx().features().coroutine_clone() { let coroutine = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine.parent_args().as_slice()), + ), + ])) } else { Err(NoSolution) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 650b85d99d2..31991565b0d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -229,7 +229,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -294,7 +294,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -1432,11 +1432,8 @@ where self.merge_trait_candidates(candidates) } - fn try_stall_coroutine_witness( - &mut self, - self_ty: I::Ty, - ) -> Option<Result<Candidate<I>, NoSolution>> { - if let ty::CoroutineWitness(def_id, _) = self_ty.kind() { + fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> { + if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e12e74c0f1a..641815f4d9a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1423,8 +1423,6 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let vis = self.tcx.local_visibility(local_def_id); - let span = self.tcx.def_span(self.item_def_id.to_def_id()); - let vis_span = self.tcx.def_span(def_id); if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) { let vis_descr = match vis { ty::Visibility::Public => "public", @@ -1441,6 +1439,8 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } }; + let span = self.tcx.def_span(self.item_def_id.to_def_id()); + let vis_span = self.tcx.def_span(def_id); self.tcx.dcx().emit_err(InPublicInterface { span, vis_descr, @@ -1463,6 +1463,8 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } else { lint::builtin::PRIVATE_BOUNDS }; + let span = self.tcx.def_span(self.item_def_id.to_def_id()); + let vis_span = self.tcx.def_span(def_id); self.tcx.emit_node_span_lint( lint, self.tcx.local_def_id_to_hir_id(self.item_def_id), @@ -1594,7 +1596,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { self.effective_visibilities.effective_vis(def_id).copied() } - fn check_item(&mut self, id: ItemId) { + fn check_item(&self, id: ItemId) { let tcx = self.tcx; let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); @@ -1722,7 +1724,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { } } - fn check_foreign_item(&mut self, id: ForeignItemId) { + fn check_foreign_item(&self, id: ForeignItemId) { let tcx = self.tcx; let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); @@ -1854,16 +1856,12 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { tcx.arena.alloc(visitor.effective_visibilities) } -fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { +fn check_private_in_public(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let effective_visibilities = tcx.effective_visibilities(()); // Check for private types in public interfaces. - let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities }; + let checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities }; - let crate_items = tcx.hir_crate_items(()); - for id in crate_items.free_items() { - checker.check_item(id); - } - for id in crate_items.foreign_items() { - checker.check_foreign_item(id); - } + let crate_items = tcx.hir_module_items(module_def_id); + let _ = crate_items.par_items(|id| Ok(checker.check_item(id))); + let _ = crate_items.par_foreign_items(|id| Ok(checker.check_foreign_item(id))); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b14a6edb791..3b57f6e883a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -801,10 +801,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } err.multipart_suggestion(msg, suggestions, applicability); } - if let Some(ModuleOrUniformRoot::Module(module)) = module - && let Some(module) = module.opt_def_id() - && let Some(segment) = segment - { + + if let Some(segment) = segment { + let module = match module { + Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id, + _ => CRATE_DEF_ID.to_def_id(), + }; self.find_cfg_stripped(&mut err, &segment, module); } @@ -2839,16 +2841,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { continue; } - let note = errors::FoundItemConfigureOut { span: ident.span }; - err.subdiagnostic(note); - - if let CfgEntry::NameValue { value: Some((feature, _)), .. } = cfg.0 { - let note = errors::ItemWasBehindFeature { feature, span: cfg.1 }; - err.subdiagnostic(note); + let item_was = if let CfgEntry::NameValue { value: Some((feature, _)), .. } = cfg.0 { + errors::ItemWas::BehindFeature { feature, span: cfg.1 } } else { - let note = errors::ItemWasCfgOut { span: cfg.1 }; - err.subdiagnostic(note); - } + errors::ItemWas::CfgOut { span: cfg.1 } + }; + let note = errors::FoundItemConfigureOut { span: ident.span, item_was }; + err.subdiagnostic(note); } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index d6b1e4de6ea..2747ba135ed 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,10 +1,13 @@ use rustc_errors::codes::*; -use rustc_errors::{Applicability, ElidedLifetimeInPathSubdiag, MultiSpan}; +use rustc_errors::{ + Applicability, Diag, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, MultiSpan, + Subdiagnostic, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; -use crate::Res; use crate::late::PatternSource; +use crate::{Res, fluent_generated as fluent}; #[derive(Diagnostic)] #[diag(resolve_generic_params_from_outer_item, code = E0401)] @@ -1201,26 +1204,35 @@ pub(crate) struct IdentInScopeButItIsDesc<'a> { pub(crate) imported_ident_desc: &'a str, } -#[derive(Subdiagnostic)] -#[note(resolve_found_an_item_configured_out)] pub(crate) struct FoundItemConfigureOut { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Subdiagnostic)] -#[note(resolve_item_was_behind_feature)] -pub(crate) struct ItemWasBehindFeature { - pub(crate) feature: Symbol, - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Subdiagnostic)] -#[note(resolve_item_was_cfg_out)] -pub(crate) struct ItemWasCfgOut { - #[primary_span] pub(crate) span: Span, + pub(crate) item_was: ItemWas, +} + +pub(crate) enum ItemWas { + BehindFeature { feature: Symbol, span: Span }, + CfgOut { span: Span }, +} + +impl Subdiagnostic for FoundItemConfigureOut { + fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { + let mut multispan: MultiSpan = self.span.into(); + match self.item_was { + ItemWas::BehindFeature { feature, span } => { + let key = "feature".into(); + let value = feature.into_diag_arg(&mut None); + let msg = diag.dcx.eagerly_translate_to_string( + fluent::resolve_item_was_behind_feature, + [(&key, &value)].into_iter(), + ); + multispan.push_span_label(span, msg); + } + ItemWas::CfgOut { span } => { + multispan.push_span_label(span, fluent::resolve_item_was_cfg_out); + } + } + diag.span_note(multispan, fluent::resolve_found_an_item_configured_out); + } } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 261d099abdc..163e4b5b7a9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4231,13 +4231,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // // And that's what happens below - we're just mixing both messages // into a single one. + let failed_to_resolve = match parent_err.node { + ResolutionError::FailedToResolve { .. } => true, + _ => false, + }; let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); // overwrite all properties with the parent's error message err.messages = take(&mut parent_err.messages); err.code = take(&mut parent_err.code); swap(&mut err.span, &mut parent_err.span); - err.children = take(&mut parent_err.children); + if failed_to_resolve { + err.children = take(&mut parent_err.children); + } else { + err.children.append(&mut parent_err.children); + } err.sort_span = parent_err.sort_span; err.is_lint = parent_err.is_lint.clone(); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 98e48664e68..236b1404eeb 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -525,9 +525,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } self.err_code_special_cases(&mut err, source, path, span); - if let Some(module) = base_error.module { - self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module); - } + let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); + self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module); (err, candidates) } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 97d1d9c2d2a..19494ffc37e 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -768,7 +768,9 @@ impl SyntaxContext { /// /// ```rust /// #![feature(decl_macro)] - /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty. + /// mod foo { + /// pub fn f() {} // `f`'s `SyntaxContext` is empty. + /// } /// m!(f); /// macro m($f:ident) { /// mod bar { diff --git a/compiler/rustc_thread_pool/src/scope/mod.rs b/compiler/rustc_thread_pool/src/scope/mod.rs index 38230383965..677009a9bc3 100644 --- a/compiler/rustc_thread_pool/src/scope/mod.rs +++ b/compiler/rustc_thread_pool/src/scope/mod.rs @@ -501,9 +501,9 @@ impl<'scope> Scope<'scope> { /// let mut value_c = None; /// rayon::scope(|s| { /// s.spawn(|s1| { - /// // ^ this is the same scope as `s`; this handle `s1` - /// // is intended for use by the spawned task, - /// // since scope handles cannot cross thread boundaries. + /// // ^ this is the same scope as `s`; this handle `s1` + /// // is intended for use by the spawned task, + /// // since scope handles cannot cross thread boundaries. /// /// value_a = Some(22); /// diff --git a/compiler/rustc_thread_pool/src/sleep/mod.rs b/compiler/rustc_thread_pool/src/sleep/mod.rs index 31bf7184b42..aa666609214 100644 --- a/compiler/rustc_thread_pool/src/sleep/mod.rs +++ b/compiler/rustc_thread_pool/src/sleep/mod.rs @@ -44,7 +44,7 @@ impl SleepData { /// jobs are published, and it either blocks threads or wakes them in response to these /// events. See the [`README.md`] in this module for more details. /// -/// [`README.md`] README.md +/// [`README.md`]: README.md pub(super) struct Sleep { /// One "sleep state" per worker. Used to track if a worker is sleeping and to have /// them block. diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 01bdae7435d..3f628d80662 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -355,7 +355,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> { return ControlFlow::Continue(()); } - if let ty::CoroutineWitness(def_id, _) = *ty.kind() + if let ty::Coroutine(def_id, _) = *ty.kind() && def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id)) { ControlFlow::Break(()) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 38cfdcdc22d..b1b331d1b61 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -318,7 +318,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( }) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when coroutine yields // (and is subsequently dropped). @@ -346,7 +346,10 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // While we conservatively assume that all coroutines require drop // to avoid query cycles during MIR building, we can check the actual // witness during borrowck to avoid unnecessary liveness constraints. - if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) { + let typing_env = tcx.erase_regions(typing_env); + if tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| { + witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env)) + }) { constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 2c7089507a8..62795c8a3a6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -794,18 +794,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The auto impl might apply; we don't know. candidates.ambiguous = true; } - ty::Coroutine(coroutine_def_id, _) - if self.tcx().is_lang_item(def_id, LangItem::Unpin) => - { - match self.tcx().coroutine_movability(coroutine_def_id) { - hir::Movability::Static => { - // Immovable coroutines are never `Unpin`, so - // suppress the normal auto-impl candidate for it. + ty::Coroutine(coroutine_def_id, _) => { + if self.tcx().is_lang_item(def_id, LangItem::Unpin) { + match self.tcx().coroutine_movability(coroutine_def_id) { + hir::Movability::Static => { + // Immovable coroutines are never `Unpin`, so + // suppress the normal auto-impl candidate for it. + } + hir::Movability::Movable => { + // Movable coroutines are always `Unpin`, so add an + // unconditional builtin candidate with no sub-obligations. + candidates.vec.push(BuiltinCandidate); + } } - hir::Movability::Movable => { - // Movable coroutines are always `Unpin`, so add an - // unconditional builtin candidate. - candidates.vec.push(BuiltinCandidate); + } else { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + } else { + // Coroutines implement all other auto traits normally. + candidates.vec.push(AutoImplCandidate); } } } @@ -842,12 +849,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(def_id, _) => { - if self.should_stall_coroutine_witness(def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(AutoImplCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(AutoImplCandidate); } ty::Bool @@ -866,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnPtr(..) | ty::Closure(..) | ty::CoroutineClosure(..) - | ty::Coroutine(..) | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) => { @@ -1153,15 +1155,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Ref(_, _, hir::Mutability::Mut) => {} ty::Coroutine(coroutine_def_id, args) => { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + return; + } + match self.tcx().coroutine_movability(coroutine_def_id) { hir::Movability::Static => {} hir::Movability::Movable => { if self.tcx().features().coroutine_clone() { let resolved_upvars = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let resolved_witness = - self.infcx.shallow_resolve(args.as_coroutine().witness()); - if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() { + if resolved_upvars.is_ty_var() { // Not yet resolved. candidates.ambiguous = true; } else { @@ -1194,12 +1199,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(SizedCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); } // Fallback to whatever user-defined impls or param-env clauses exist in this case. @@ -1238,7 +1239,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(..) | ty::Char | ty::Ref(..) - | ty::Coroutine(..) | ty::Array(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1247,14 +1247,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(SizedCandidate); } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { + ty::Coroutine(coroutine_def_id, _) => { + if self.should_stall_coroutine(coroutine_def_id) { candidates.ambiguous = true; } else { candidates.vec.push(SizedCandidate); } } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); + } + // Conditionally `Sized`. ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => { candidates.vec.push(SizedCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7c3543cb3f..7ea1548f8f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2196,7 +2196,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { args.as_coroutine() .upvar_tys() .iter() - .chain([args.as_coroutine().witness()]) + .chain([Ty::new_coroutine_witness( + self.tcx(), + coroutine_def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + )]) .collect::<Vec<_>>(), ) } else { @@ -2327,9 +2331,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Binder::dummy(AutoImplConstituents { types: vec![ty], assumptions: vec![] }) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let witness = args.as_coroutine().witness(); + let witness = Ty::new_coroutine_witness( + self.tcx(), + def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + ); ty::Binder::dummy(AutoImplConstituents { types: [ty].into_iter().chain(iter::once(witness)).collect(), assumptions: vec![], @@ -2841,7 +2849,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligations } - fn should_stall_coroutine_witness(&self, def_id: DefId) -> bool { + fn should_stall_coroutine(&self, def_id: DefId) -> bool { match self.infcx.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => { def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id)) diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index c3b04c20f4b..13d56889bd1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -101,9 +101,6 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - /// Whether to reveal coroutine witnesses, this is set - /// to `false` unless we compute `needs_drop` for a coroutine witness. - reveal_coroutine_witnesses: bool, query_ty: Ty<'tcx>, seen_tys: FxHashSet<Ty<'tcx>>, /// A stack of types left to process, and the recursion depth when we @@ -115,6 +112,15 @@ struct NeedsDropTypes<'tcx, F> { adt_components: F, /// Set this to true if an exhaustive list of types involved in /// drop obligation is requested. + // FIXME: Calling this bool `exhaustive` is confusing and possibly a footgun, + // since it does two things: It makes the iterator yield *all* of the types + // that need drop, and it also affects the computation of the drop components + // on `Coroutine`s. The latter is somewhat confusing, and probably should be + // a function of `typing_env`. See the HACK comment below for why this is + // necessary. If this isn't possible, then we probably should turn this into + // a `NeedsDropMode` so that we can have a variant like `CollectAllSignificantDrops`, + // which will more accurately indicate that we want *all* of the *significant* + // drops, which are the two important behavioral changes toggled by this bool. exhaustive: bool, } @@ -131,7 +137,6 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { Self { tcx, typing_env, - reveal_coroutine_witnesses: exhaustive, seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], @@ -195,23 +200,27 @@ where // for the coroutine witness and check whether any of the contained types // need to be dropped, and only require the captured types to be live // if they do. - ty::Coroutine(_, args) => { - if self.reveal_coroutine_witnesses { - queue_type(self, args.as_coroutine().witness()); + ty::Coroutine(def_id, args) => { + // FIXME: See FIXME on `exhaustive` field above. + if self.exhaustive { + for upvar in args.as_coroutine().upvar_tys() { + queue_type(self, upvar); + } + queue_type(self, args.as_coroutine().resume_ty()); + if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) { + for field_ty in &witness.field_tys { + queue_type( + self, + EarlyBinder::bind(field_ty.ty).instantiate(tcx, args), + ); + } + } } else { return Some(self.always_drop_component(ty)); } } - ty::CoroutineWitness(def_id, args) => { - if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) { - self.reveal_coroutine_witnesses = true; - for field_ty in &witness.field_tys { - queue_type( - self, - EarlyBinder::bind(field_ty.ty).instantiate(tcx, args), - ); - } - } + ty::CoroutineWitness(..) => { + unreachable!("witness should be handled in parent"); } ty::UnsafeBinder(bound_ty) => { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d7b9e0ca340..23b7f55fbbe 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -131,10 +131,7 @@ bitflags::bitflags! { /// Does this have any binders with bound vars (e.g. that need to be anonymized)? const HAS_BINDER_VARS = 1 << 23; - /// Does this type have any coroutine witnesses in it? - // FIXME: This should probably be changed to track whether the type has any - // *coroutines* in it, though this will happen if we remove coroutine witnesses - // altogether. + /// Does this type have any coroutines in it? const HAS_TY_CORO = 1 << 24; } } @@ -246,11 +243,13 @@ impl<I: Interner> FlagComputation<I> { self.add_flags(TypeFlags::HAS_TY_PARAM); } - ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) => { + ty::Closure(_, args) + | ty::CoroutineClosure(_, args) + | ty::CoroutineWitness(_, args) => { self.add_args(args.as_slice()); } - ty::CoroutineWitness(_, args) => { + ty::Coroutine(_, args) => { self.add_flags(TypeFlags::HAS_TY_CORO); self.add_args(args.as_slice()); } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fb..c32f8339d0b 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -101,7 +101,6 @@ use crate::{self as ty, Interner}; /// `yield` inside the coroutine. /// * `GR`: The "return type", which is the type of value returned upon /// completion of the coroutine. -/// * `GW`: The "coroutine witness". #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct ClosureArgs<I: Interner> { @@ -239,8 +238,6 @@ pub struct CoroutineClosureArgsParts<I: Interner> { /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. pub coroutine_captures_by_ref_ty: I::Ty, - /// Witness type returned by the generator produced by this coroutine-closure. - pub coroutine_witness_ty: I::Ty, } impl<I: Interner> CoroutineClosureArgs<I> { @@ -251,7 +248,6 @@ impl<I: Interner> CoroutineClosureArgs<I> { parts.signature_parts_ty.into(), parts.tupled_upvars_ty.into(), parts.coroutine_captures_by_ref_ty.into(), - parts.coroutine_witness_ty.into(), ])), } } @@ -292,7 +288,6 @@ impl<I: Interner> CoroutineClosureArgs<I> { } pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> { - let interior = self.coroutine_witness_ty(); let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() }; sig_tys.map_bound(|sig_tys| { let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else { @@ -302,7 +297,6 @@ impl<I: Interner> CoroutineClosureArgs<I> { panic!() }; CoroutineClosureSignature { - interior, tupled_inputs_ty, resume_ty, yield_ty, @@ -318,10 +312,6 @@ impl<I: Interner> CoroutineClosureArgs<I> { self.split().coroutine_captures_by_ref_ty } - pub fn coroutine_witness_ty(self) -> I::Ty { - self.split().coroutine_witness_ty - } - pub fn has_self_borrows(&self) -> bool { match self.coroutine_captures_by_ref_ty().kind() { ty::FnPtr(sig_tys, _) => sig_tys @@ -361,7 +351,6 @@ impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct CoroutineClosureSignature<I: Interner> { - pub interior: I::Ty, pub tupled_inputs_ty: I::Ty, pub resume_ty: I::Ty, pub yield_ty: I::Ty, @@ -407,7 +396,6 @@ impl<I: Interner> CoroutineClosureSignature<I> { resume_ty: self.resume_ty, yield_ty: self.yield_ty, return_ty: self.return_ty, - witness: self.interior, tupled_upvars_ty, }, ); @@ -587,11 +575,6 @@ pub struct CoroutineArgsParts<I: Interner> { pub yield_ty: I::Ty, pub return_ty: I::Ty, - /// The interior type of the coroutine. - /// Represents all types that are stored in locals - /// in the coroutine's body. - pub witness: I::Ty, - /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: I::Ty, @@ -607,7 +590,6 @@ impl<I: Interner> CoroutineArgs<I> { parts.resume_ty.into(), parts.yield_ty.into(), parts.return_ty.into(), - parts.witness.into(), parts.tupled_upvars_ty.into(), ])), } @@ -629,15 +611,6 @@ impl<I: Interner> CoroutineArgs<I> { self.split().kind_ty } - /// This describes the types that can be contained in a coroutine. - /// It will be a type variable initially and unified in the last stages of typeck of a body. - /// It contains a tuple of all the types that could end up on a coroutine frame. - /// The state transformation MIR pass may only produce layouts which mention types - /// in this tuple. Upvars are not counted here. - pub fn witness(self) -> I::Ty { - self.split().witness - } - /// Returns an iterator over the list of types of captured paths by the coroutine. /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index d58240f3051..9eacbf00e42 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -265,12 +265,12 @@ use crate::vec::{self, Vec}; /// You can look at these with the [`as_ptr`], [`len`], and [`capacity`] /// methods: /// +// FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// use std::mem; /// /// let story = String::from("Once upon a time..."); /// -// FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent automatically dropping the String's data /// let mut story = mem::ManuallyDrop::new(story); /// @@ -970,13 +970,13 @@ impl String { /// /// # Examples /// + // FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// use std::mem; /// /// unsafe { /// let s = String::from("hello"); /// - // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent automatically dropping the String's data /// let mut s = mem::ManuallyDrop::new(s); /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ce74615dbcc..2321aab2c51 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -566,13 +566,13 @@ impl<T> Vec<T> { /// /// # Examples /// + // FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// use std::ptr; /// use std::mem; /// /// let v = vec![1, 2, 3]; /// - // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control /// // of the allocation. /// let mut v = mem::ManuallyDrop::new(v); @@ -674,6 +674,7 @@ impl<T> Vec<T> { /// /// # Examples /// + // FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// #![feature(box_vec_non_null)] /// @@ -682,7 +683,6 @@ impl<T> Vec<T> { /// /// let v = vec![1, 2, 3]; /// - // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control /// // of the allocation. /// let mut v = mem::ManuallyDrop::new(v); @@ -994,6 +994,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Examples /// + // FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// #![feature(allocator_api)] /// @@ -1007,7 +1008,6 @@ impl<T, A: Allocator> Vec<T, A> { /// v.push(2); /// v.push(3); /// - // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control /// // of the allocation. /// let mut v = mem::ManuallyDrop::new(v); @@ -1114,6 +1114,7 @@ impl<T, A: Allocator> Vec<T, A> { /// /// # Examples /// + // FIXME Update this when vec_into_raw_parts is stabilized /// ``` /// #![feature(allocator_api, box_vec_non_null)] /// @@ -1127,7 +1128,6 @@ impl<T, A: Allocator> Vec<T, A> { /// v.push(2); /// v.push(3); /// - // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control /// // of the allocation. /// let mut v = mem::ManuallyDrop::new(v); @@ -3872,8 +3872,8 @@ impl<T, A: Allocator> Vec<T, A> { /// while i < vec.len() - end_items { /// if some_predicate(&mut vec[i]) { /// let val = vec.remove(i); - /// # extracted.push(val); /// // your code here + /// # extracted.push(val); /// } else { /// i += 1; /// } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d6d1bf2effa..d67408cae1b 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2068,9 +2068,9 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// implies exclusive access to its `T`: /// /// ```rust -/// #![forbid(unsafe_code)] // with exclusive accesses, -/// // `UnsafeCell` is a transparent no-op wrapper, -/// // so no need for `unsafe` here. +/// #![forbid(unsafe_code)] +/// // with exclusive accesses, `UnsafeCell` is a transparent no-op wrapper, so no need for +/// // `unsafe` here. /// use std::cell::UnsafeCell; /// /// let mut x: UnsafeCell<i32> = 42.into(); diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 696d323c66d..c72eeb9a9c9 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -649,8 +649,6 @@ pub const fn must_use<T>(value: T) -> T { /// } /// } /// ``` -/// -/// #[unstable(feature = "likely_unlikely", issue = "136873")] #[inline(always)] pub const fn likely(b: bool) -> bool { diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 7ca41d224a0..56ca1305b60 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -233,10 +233,12 @@ //! //! ``` //! let mut values = vec![41]; -//! for x in &mut values { // same as `values.iter_mut()` +//! for x in &mut values { +//! // ^ same as `values.iter_mut()` //! *x += 1; //! } -//! for x in &values { // same as `values.iter()` +//! for x in &values { +//! // ^ same as `values.iter()` //! assert_eq!(*x, 42); //! } //! assert_eq!(values.len(), 1); diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 10f9d464f7d..29313867ff2 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -807,7 +807,7 @@ pub trait Iterator { /// might be preferable to keep a functional style with longer iterators: /// /// ``` - /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// (0..5).flat_map(|x| (x * 100)..(x * 110)) /// .enumerate() /// .filter(|&(i, x)| (i + x) % 3 == 0) /// .for_each(|(i, x)| println!("{i}:{x}")); diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3d57da63683..c59290a757b 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -271,7 +271,10 @@ pub macro cfg_select($($tt:tt)*) { /// // expression given. /// debug_assert!(true); /// -/// fn some_expensive_computation() -> bool { true } // a very simple function +/// fn some_expensive_computation() -> bool { +/// // Some expensive computation here +/// true +/// } /// debug_assert!(some_expensive_computation()); /// /// // assert with a custom message @@ -1547,7 +1550,10 @@ pub(crate) mod builtin { /// // expression given. /// assert!(true); /// - /// fn some_computation() -> bool { true } // a very simple function + /// fn some_computation() -> bool { + /// // Some expensive computation here + /// true + /// } /// /// assert!(some_computation()); /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 45277a1c82d..ba00ee17b65 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -138,8 +138,7 @@ unsafe impl<T: Sync + PointeeSized> Send for &T {} /// impl Bar for Impl { } /// /// let x: &dyn Foo = &Impl; // OK -/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot -/// // be made into an object +/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot be made into an object /// ``` /// /// [trait object]: ../../book/ch17-02-trait-objects.html diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 34d8370da7e..c160360cfac 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -773,8 +773,7 @@ impl<T> MaybeUninit<T> { /// // Initialize the `MaybeUninit` using `Cell::set`: /// unsafe { /// b.assume_init_ref().set(true); - /// // ^^^^^^^^^^^^^^^ - /// // Reference to an uninitialized `Cell<bool>`: UB! + /// //^^^^^^^^^^^^^^^ Reference to an uninitialized `Cell<bool>`: UB! /// } /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] @@ -864,9 +863,9 @@ impl<T> MaybeUninit<T> { /// { /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); /// reader.read_exact(unsafe { buffer.assume_init_mut() })?; - /// // ^^^^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// Ok(unsafe { buffer.assume_init() }) /// } /// ``` @@ -884,13 +883,13 @@ impl<T> MaybeUninit<T> { /// let foo: Foo = unsafe { /// let mut foo = MaybeUninit::<Foo>::uninit(); /// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337); - /// // ^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42); - /// // ^^^^^^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. /// foo.assume_init() /// }; /// ``` diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 9a1ba7d1728..1c824e336be 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -271,6 +271,7 @@ mod prim_bool {} /// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a /// coercion to allow the type checker to infer any type: /// +// FIXME: use `core::convert::absurd` here instead, once it's merged /// ```rust,ignore (illustrative-and-has-placeholders) /// // this /// let x: u8 = panic!(); @@ -281,7 +282,6 @@ mod prim_bool {} /// // where absurd is a function with the following signature /// // (it's sound, because `!` always marks unreachable code): /// fn absurd<T>(_: !) -> T { ... } -// FIXME: use `core::convert::absurd` here instead, once it's merged /// ``` /// /// This can lead to compilation errors if the type cannot be inferred: diff --git a/library/core/src/result.rs b/library/core/src/result.rs index f65257ff59b..474f86395ae 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -534,6 +534,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FusedIterator, TrustedLen}; +use crate::marker::Destruct; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; @@ -606,7 +607,13 @@ impl<T, E> Result<T, E> { #[must_use] #[inline] #[stable(feature = "is_some_and", since = "1.70.0")] - pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn is_ok_and<F>(self, f: F) -> bool + where + F: ~const FnOnce(T) -> bool + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, + { match self { Err(_) => false, Ok(x) => f(x), @@ -655,7 +662,13 @@ impl<T, E> Result<T, E> { #[must_use] #[inline] #[stable(feature = "is_some_and", since = "1.70.0")] - pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn is_err_and<F>(self, f: F) -> bool + where + F: ~const FnOnce(E) -> bool + ~const Destruct, + E: ~const Destruct, + T: ~const Destruct, + { match self { Ok(_) => false, Err(e) => f(e), @@ -682,8 +695,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[rustc_diagnostic_item = "result_ok_method"] - pub fn ok(self) -> Option<T> { + pub const fn ok(self) -> Option<T> + where + T: ~const Destruct, + E: ~const Destruct, + { match self { Ok(x) => Some(x), Err(_) => None, @@ -706,7 +724,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn err(self) -> Option<E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn err(self) -> Option<E> + where + T: ~const Destruct, + E: ~const Destruct, + { match self { Ok(_) => None, Err(x) => Some(x), @@ -796,7 +819,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map<U, F>(self, op: F) -> Result<U, E> + where + F: ~const FnOnce(T) -> U + ~const Destruct, + { match self { Ok(t) => Ok(op(t)), Err(e) => Err(e), @@ -823,8 +850,15 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_map_or", since = "1.41.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[must_use = "if you don't need the returned value, use `if let` instead"] - pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U { + pub const fn map_or<U, F>(self, default: U, f: F) -> U + where + F: ~const FnOnce(T) -> U + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, + U: ~const Destruct, + { match self { Ok(t) => f(t), Err(_) => default, @@ -851,7 +885,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_map_or_else", since = "1.41.0")] - pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U + where + D: ~const FnOnce(E) -> U + ~const Destruct, + F: ~const FnOnce(T) -> U + ~const Destruct, + { match self { Ok(t) => f(t), Err(e) => default(e), @@ -877,10 +916,13 @@ impl<T, E> Result<T, E> { /// [default value]: Default::default #[inline] #[unstable(feature = "result_option_map_or_default", issue = "138099")] - pub fn map_or_default<U, F>(self, f: F) -> U + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_or_default<U, F>(self, f: F) -> U where - U: Default, - F: FnOnce(T) -> U, + F: ~const FnOnce(T) -> U + ~const Destruct, + U: ~const Default, + T: ~const Destruct, + E: ~const Destruct, { match self { Ok(t) => f(t), @@ -908,7 +950,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn map_err<F, O>(self, op: O) -> Result<T, F> + where + O: ~const FnOnce(E) -> F + ~const Destruct, + { match self { Ok(t) => Ok(t), Err(e) => Err(op(e)), @@ -930,7 +976,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] - pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn inspect<F>(self, f: F) -> Self + where + F: ~const FnOnce(&T) + ~const Destruct, + { if let Ok(ref t) = self { f(t); } @@ -954,7 +1004,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] - pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn inspect_err<F>(self, f: F) -> Self + where + F: ~const FnOnce(&E) + ~const Destruct, + { if let Err(ref e) = self { f(e); } @@ -1033,7 +1087,8 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter<'_, T> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn iter(&self) -> Iter<'_, T> { Iter { inner: self.as_ref().ok() } } @@ -1056,7 +1111,8 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut<'_, T> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { inner: self.as_mut().ok() } } @@ -1195,9 +1251,11 @@ impl<T, E> Result<T, E> { /// [`FromStr`]: crate::str::FromStr #[inline] #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] - pub fn unwrap_or_default(self) -> T + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or_default(self) -> T where - T: Default, + T: ~const Default + ~const Destruct, + E: ~const Destruct, { match self { Ok(x) => x, @@ -1370,7 +1428,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> + where + T: ~const Destruct, + E: ~const Destruct, + U: ~const Destruct, + { match self { Ok(_) => res, Err(e) => Err(e), @@ -1409,8 +1473,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] #[rustc_confusables("flat_map", "flatmap")] - pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> { + pub const fn and_then<U, F>(self, op: F) -> Result<U, E> + where + F: ~const FnOnce(T) -> Result<U, E> + ~const Destruct, + { match self { Ok(t) => op(t), Err(e) => Err(e), @@ -1446,7 +1514,13 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> + where + T: ~const Destruct, + E: ~const Destruct, + F: ~const Destruct, + { match self { Ok(v) => Ok(v), Err(_) => res, @@ -1471,7 +1545,11 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn or_else<F, O>(self, op: O) -> Result<T, F> + where + O: ~const FnOnce(E) -> Result<T, F> + ~const Destruct, + { match self { Ok(t) => Ok(t), Err(e) => op(e), @@ -1498,7 +1576,12 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or(self, default: T) -> T + where + T: ~const Destruct, + E: ~const Destruct, + { match self { Ok(t) => t, Err(_) => default, @@ -1519,7 +1602,11 @@ impl<T, E> Result<T, E> { #[inline] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T { + #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")] + pub const fn unwrap_or_else<F>(self, op: F) -> T + where + F: ~const FnOnce(E) -> T + ~const Destruct, + { match self { Ok(t) => t, Err(e) => op(e), @@ -1544,7 +1631,7 @@ impl<T, E> Result<T, E> { /// /// ```no_run /// let x: Result<u32, &str> = Err("emergency failure"); - /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! + /// unsafe { x.unwrap_unchecked() }; // Undefined behavior! /// ``` #[inline] #[track_caller] @@ -1762,7 +1849,7 @@ impl<T, E> Result<Result<T, E>, E> { #[cold] #[track_caller] fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { - panic!("{msg}: {error:?}") + panic!("{msg}: {error:?}"); } // This is a separate function to avoid constructing a `dyn Debug` @@ -1773,7 +1860,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { #[inline] #[cold] #[track_caller] -fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { +const fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { panic!() } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 029a7b00ad3..0a9c0c61c95 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(const_eval_select)] #![feature(const_ops)] #![feature(const_ref_cell)] +#![feature(const_result_trait_fn)] #![feature(const_trait_impl)] #![feature(core_float_math)] #![feature(core_intrinsics)] @@ -82,6 +83,7 @@ #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] #![feature(ptr_metadata)] +#![feature(result_option_map_or_default)] #![feature(slice_from_ptr_range)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] diff --git a/library/coretests/tests/result.rs b/library/coretests/tests/result.rs index 90ec844bc57..39898d5dbb7 100644 --- a/library/coretests/tests/result.rs +++ b/library/coretests/tests/result.rs @@ -421,3 +421,86 @@ fn result_try_trait_v2_branch() { assert_eq!(Ok::<NonZero<u32>, ()>(one).branch(), Continue(one)); assert_eq!(Err::<NonZero<u32>, ()>(()).branch(), Break(Err(()))); } + +// helper functions for const contexts +const fn eq10(x: u8) -> bool { + x == 10 +} +const fn eq20(e: u8) -> bool { + e == 20 +} +const fn double_u16(x: u8) -> u16 { + x as u16 * 2 +} +const fn to_u16(x: u8) -> u16 { + x as u16 +} +const fn err_to_u16_plus1(e: u8) -> u16 { + e as u16 + 1 +} +const fn inc_u8(x: u8) -> u8 { + x + 1 +} +const fn noop_u8_ref(_x: &u8) {} +const fn add1_result(x: u8) -> Result<u8, u8> { + Ok(x + 1) +} +const fn add5_result(e: u8) -> Result<u8, u8> { + Ok(e + 5) +} +const fn plus7_u8(e: u8) -> u8 { + e + 7 +} + +#[test] +fn test_const_result() { + const { + let r_ok: Result<u8, u8> = Ok(10); + let r_err: Result<u8, u8> = Err(20); + assert!(r_ok.is_ok()); + assert!(r_err.is_err()); + + let ok_and = r_ok.is_ok_and(eq10); + let err_and = r_err.is_err_and(eq20); + assert!(ok_and); + assert!(err_and); + + let opt_ok: Option<u8> = r_ok.ok(); + let opt_err: Option<u8> = r_err.err(); + assert!(opt_ok.unwrap() == 10); + assert!(opt_err.unwrap() == 20); + + let mapped: Result<u16, u8> = r_ok.map(double_u16); + let map_or: u16 = r_ok.map_or(0, to_u16); + let map_or_else: u16 = r_err.map_or_else(err_to_u16_plus1, to_u16); + let map_or_default: u8 = r_err.map_or_default(inc_u8); + assert!(mapped.unwrap_or_default() == 20); + assert!(map_or == 10); + assert!(map_or_else == 21); + assert!(map_or_default == 0); + + let _map_err: Result<u8, u16> = r_err.map_err(to_u16); + //FIXME: currently can't unwrap const error + // assert!(map_err.unwrap_err() == 20); + + let inspected_ok: Result<u8, u8> = r_ok.inspect(noop_u8_ref); + let inspected_err: Result<u8, u8> = r_err.inspect_err(noop_u8_ref); + assert!(inspected_ok.is_ok()); + assert!(inspected_err.is_err()); + + let unwrapped_default: u8 = r_err.unwrap_or_default(); + assert!(unwrapped_default == 0); + + let and_then: Result<u8, u8> = r_ok.and_then(add1_result); + let or: Result<u8, u8> = r_err.or(Ok(5)); + let or_else: Result<u8, u8> = r_err.or_else(add5_result); + assert!(and_then.unwrap_or_default() == 11); + assert!(or.unwrap_or_default() == 5); + assert!(or_else.unwrap_or_default() == 25); + + let u_or: u8 = r_err.unwrap_or(7); + let u_or_else: u8 = r_err.unwrap_or_else(plus7_u8); + assert!(u_or == 7); + assert!(u_or_else == 27); + }; +} diff --git a/library/std/src/path.rs b/library/std/src/path.rs index d9c34d4fa04..055e7f81480 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3259,8 +3259,8 @@ impl Path { /// /// # Examples /// - #[cfg_attr(unix, doc = "```no_run")] - #[cfg_attr(not(unix), doc = "```ignore")] + /// ```rust,no_run + /// # #[cfg(unix)] { /// use std::path::Path; /// use std::os::unix::fs::symlink; /// @@ -3268,6 +3268,7 @@ impl Path { /// symlink("/origin_does_not_exist/", link_path).unwrap(); /// assert_eq!(link_path.is_symlink(), true); /// assert_eq!(link_path.exists(), false); + /// # } /// ``` /// /// # See Also diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index a5c3a6c46a4..b224044cbe0 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -16,6 +16,8 @@ use crate::sync::Once; /// A `OnceLock` can be thought of as a safe abstraction over uninitialized data that becomes /// initialized once written. /// +/// Unlike [`Mutex`](crate::sync::Mutex), `OnceLock` is never poisoned on panic. +/// /// [`OnceCell`]: crate::cell::OnceCell /// [`LazyLock<T, F>`]: crate::sync::LazyLock /// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index b901a5701a4..d5adc9e29b5 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -2,15 +2,16 @@ //! //! # Poisoning //! -//! All synchronization objects in this module implement a strategy called "poisoning" -//! where if a thread panics while holding the exclusive access granted by the primitive, -//! the state of the primitive is set to "poisoned". -//! This information is then propagated to all other threads +//! All synchronization objects in this module implement a strategy called +//! "poisoning" where a primitive becomes poisoned if it recognizes that some +//! thread has panicked while holding the exclusive access granted by the +//! primitive. This information is then propagated to all other threads //! to signify that the data protected by this primitive is likely tainted //! (some invariant is not being upheld). //! -//! The specifics of how this "poisoned" state affects other threads -//! depend on the primitive. See [#Overview] below. +//! The specifics of how this "poisoned" state affects other threads and whether +//! the panics are recognized reliably or on a best-effort basis depend on the +//! primitive. See [#Overview] below. //! //! For the alternative implementations that do not employ poisoning, //! see [`std::sync::nonpoison`]. @@ -36,14 +37,15 @@ //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at //! most one thread at a time is able to access some data. //! -//! [`Mutex::lock()`] returns a [`LockResult`], -//! providing a way to deal with the poisoned state. -//! See [`Mutex`'s documentation](Mutex#poisoning) for more. +//! Panicking while holding the lock typically poisons the mutex, but it is +//! not guaranteed to detect this condition in all circumstances. +//! [`Mutex::lock()`] returns a [`LockResult`], providing a way to deal with +//! the poisoned state. See [`Mutex`'s documentation](Mutex#poisoning) for more. //! //! - [`Once`]: A thread-safe way to run a piece of code only once. //! Mostly useful for implementing one-time global initialization. //! -//! [`Once`] is poisoned if the piece of code passed to +//! [`Once`] is reliably poisoned if the piece of code passed to //! [`Once::call_once()`] or [`Once::call_once_force()`] panics. //! When in poisoned state, subsequent calls to [`Once::call_once()`] will panic too. //! [`Once::call_once_force()`] can be used to clear the poisoned state. @@ -53,7 +55,7 @@ //! writer at a time. In some cases, this can be more efficient than //! a mutex. //! -//! This implementation, like [`Mutex`], will become poisoned on a panic. +//! This implementation, like [`Mutex`], usually becomes poisoned on a panic. //! Note, however, that an `RwLock` may only be poisoned if a panic occurs //! while it is locked exclusively (write mode). If a panic occurs in any reader, //! then the lock will not be poisoned. diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 64744f18c74..6205c4fa4ca 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -18,20 +18,69 @@ use crate::sys::sync as sys; /// # Poisoning /// /// The mutexes in this module implement a strategy called "poisoning" where a -/// mutex is considered poisoned whenever a thread panics while holding the -/// mutex. Once a mutex is poisoned, all other threads are unable to access the -/// data by default as it is likely tainted (some invariant is not being -/// upheld). +/// mutex becomes poisoned if it recognizes that the thread holding it has +/// panicked. /// -/// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a +/// Once a mutex is poisoned, all other threads are unable to access the data by +/// default as it is likely tainted (some invariant is not being upheld). For a +/// mutex, this means that the [`lock`] and [`try_lock`] methods return a /// [`Result`] which indicates whether a mutex has been poisoned or not. Most /// usage of a mutex will simply [`unwrap()`] these results, propagating panics /// among threads to ensure that a possibly invalid invariant is not witnessed. /// -/// A poisoned mutex, however, does not prevent all access to the underlying -/// data. The [`PoisonError`] type has an [`into_inner`] method which will return -/// the guard that would have otherwise been returned on a successful lock. This -/// allows access to the data, despite the lock being poisoned. +/// Poisoning is only advisory: the [`PoisonError`] type has an [`into_inner`] +/// method which will return the guard that would have otherwise been returned +/// on a successful lock. This allows access to the data, despite the lock being +/// poisoned. +/// +/// In addition, the panic detection is not ideal, so even unpoisoned mutexes +/// need to be handled with care, since certain panics may have been skipped. +/// Here is a non-exhaustive list of situations where this might occur: +/// +/// - If a mutex is locked while a panic is underway, e.g. within a [`Drop`] +/// implementation or a [panic hook], panicking for the second time while the +/// lock is held will leave the mutex unpoisoned. Note that while double panic +/// usually aborts the program, [`catch_unwind`] can prevent this. +/// +/// - Locking and unlocking the mutex across different panic contexts, e.g. by +/// storing the guard to a [`Cell`] within [`Drop::drop`] and accessing it +/// outside, or vice versa, can affect poisoning status in an unexpected way. +/// +/// - Foreign exceptions do not currently trigger poisoning even in absence of +/// other panics. +/// +/// While this rarely happens in realistic code, `unsafe` code cannot rely on +/// poisoning for soundness, since the behavior of poisoning can depend on +/// outside context. Here's an example of **incorrect** use of poisoning: +/// +/// ```rust +/// use std::sync::Mutex; +/// +/// struct MutexBox<T> { +/// data: Mutex<*mut T>, +/// } +/// +/// impl<T> MutexBox<T> { +/// pub fn new(value: T) -> Self { +/// Self { +/// data: Mutex::new(Box::into_raw(Box::new(value))), +/// } +/// } +/// +/// pub fn replace_with(&self, f: impl FnOnce(T) -> T) { +/// let ptr = self.data.lock().expect("poisoned"); +/// // While `f` is running, the data is moved out of `*ptr`. If `f` +/// // panics, `*ptr` keeps pointing at a dropped value. The intention +/// // is that this will poison the mutex, so the following calls to +/// // `replace_with` will panic without reading `*ptr`. But since +/// // poisoning is not guaranteed to occur if this is run from a panic +/// // hook, this can lead to use-after-free. +/// unsafe { +/// (*ptr).write(f((*ptr).read())); +/// } +/// } +/// } +/// ``` /// /// [`new`]: Self::new /// [`lock`]: Self::lock @@ -39,6 +88,9 @@ use crate::sys::sync as sys; /// [`unwrap()`]: Result::unwrap /// [`PoisonError`]: super::PoisonError /// [`into_inner`]: super::PoisonError::into_inner +/// [panic hook]: crate::panic::set_hook +/// [`catch_unwind`]: crate::panic::catch_unwind +/// [`Cell`]: crate::cell::Cell /// /// # Examples /// diff --git a/library/std/src/sync/poison/once.rs b/library/std/src/sync/poison/once.rs index 103e5195407..faf2913c547 100644 --- a/library/std/src/sync/poison/once.rs +++ b/library/std/src/sync/poison/once.rs @@ -136,7 +136,8 @@ impl Once { /// it will *poison* this [`Once`] instance, causing all future invocations of /// `call_once` to also panic. /// - /// This is similar to [poisoning with mutexes][poison]. + /// This is similar to [poisoning with mutexes][poison], but this mechanism + /// is guaranteed to never skip panics within `f`. /// /// [poison]: struct.Mutex.html#poisoning #[inline] @@ -293,6 +294,9 @@ impl Once { /// Blocks the current thread until initialization has completed, ignoring /// poisoning. + /// + /// If this [`Once`] has been poisoned, this function blocks until it + /// becomes completed, unlike [`Once::wait()`], which panics in this case. #[stable(feature = "once_wait", since = "1.86.0")] pub fn wait_force(&self) { if !self.inner.is_completed() { diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 934a173425a..2c92602bc87 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -46,10 +46,12 @@ use crate::sys::sync as sys; /// /// # Poisoning /// -/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however, -/// that an `RwLock` may only be poisoned if a panic occurs while it is locked -/// exclusively (write mode). If a panic occurs in any reader, then the lock -/// will not be poisoned. +/// An `RwLock`, like [`Mutex`], will [usually] become poisoned on a panic. Note, +/// however, that an `RwLock` may only be poisoned if a panic occurs while it is +/// locked exclusively (write mode). If a panic occurs in any reader, then the +/// lock will not be poisoned. +/// +/// [usually]: super::Mutex#poisoning /// /// # Examples /// diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 89d5acb985b..782311e593b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -763,13 +763,13 @@ impl Item { .iter() .filter_map(|attr| match attr { hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) => { - Some(format!("#[link_section = \"{name}\"]")) + Some(format!("#[unsafe(link_section = \"{name}\")]")) } hir::Attribute::Parsed(AttributeKind::NoMangle(..)) => { - Some("#[no_mangle]".to_string()) + Some("#[unsafe(no_mangle)]".to_string()) } hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) => { - Some(format!("#[export_name = \"{name}\"]")) + Some(format!("#[unsafe(export_name = \"{name}\")]")) } hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) => { Some("#[non_exhaustive]".to_string()) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5a9aa2a94c8..c9fa3a4837f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -941,13 +941,21 @@ fn preprocess_link( ori_link: &MarkdownLink, dox: &str, ) -> Option<Result<PreprocessingInfo, PreprocessingError>> { + // certain link kinds cannot have their path be urls, + // so they should not be ignored, no matter how much they look like urls. + // e.g. [https://example.com/] is not a link to example.com. + let can_be_url = !matches!( + ori_link.kind, + LinkType::ShortcutUnknown | LinkType::CollapsedUnknown | LinkType::ReferenceUnknown + ); + // [] is mostly likely not supposed to be a link if ori_link.link.is_empty() { return None; } // Bail early for real links. - if ori_link.link.contains('/') { + if can_be_url && ori_link.link.contains('/') { return None; } @@ -972,7 +980,7 @@ fn preprocess_link( Ok(None) => (None, link, link), Err((err_msg, relative_range)) => { // Only report error if we would not have ignored this link. See issue #83859. - if !should_ignore_link_with_disambiguators(link) { + if !(can_be_url && should_ignore_link_with_disambiguators(link)) { let disambiguator_range = match range_between_backticks(&ori_link.range, dox) { MarkdownLinkRange::Destination(no_backticks_range) => { MarkdownLinkRange::Destination( @@ -989,7 +997,25 @@ fn preprocess_link( } }; - if should_ignore_link(path_str) { + // If there's no backticks, be lenient and revert to the old behavior. + // This is to prevent churn by linting on stuff that isn't meant to be a link. + // only shortcut links have simple enough syntax that they + // are likely to be written accidentally, collapsed and reference links + // need 4 metachars, and reference links will not usually use + // backticks in the reference name. + // therefore, only shortcut syntax gets the lenient behavior. + // + // here's a truth table for how link kinds that cannot be urls are handled: + // + // |-------------------------------------------------------| + // | | is shortcut link | not shortcut link | + // |--------------|--------------------|-------------------| + // | has backtick | never ignore | never ignore | + // | no backtick | ignore if url-like | never ignore | + // |-------------------------------------------------------| + let ignore_urllike = + can_be_url || (ori_link.kind == LinkType::ShortcutUnknown && !ori_link.link.contains('`')); + if ignore_urllike && should_ignore_link(path_str) { return None; } diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 9b296973b425ffb159e12cf3cd56580fd5c8538 +Subproject 840b83a10fb0e039a83f4d70ad032892c287570 diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs index f5e2f18e68e..2892ff2882a 100644 --- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs +++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs @@ -1,17 +1,24 @@ -// Test LVI load hardening on SGX enclave code +// Test LVI load hardening on SGX enclave code, specifically that `ret` is rewritten. +//@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --crate-type staticlib -//@ only-x86_64-fortanix-unknown-sgx +//@ compile-flags: --target x86_64-fortanix-unknown-sgx -Copt-level=0 +//@ needs-llvm-components: x86 + +#![feature(no_core, lang_items, f16)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; #[no_mangle] -pub extern "C" fn plus_one(r: &mut u64) { - *r = *r + 1; +pub extern "C" fn dereference(a: &mut u64) -> u64 { + // CHECK-LABEL: dereference + // CHECK: lfence + // CHECK: mov + // CHECK: popq [[REGISTER:%[a-z]+]] + // CHECK-NEXT: lfence + // CHECK-NEXT: jmpq *[[REGISTER]] + *a } - -// CHECK: plus_one -// CHECK: lfence -// CHECK-NEXT: incq -// CHECK: popq [[REGISTER:%[a-z]+]] -// CHECK-NEXT: lfence -// CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs index f16d68fa255..a0cedc3bc2d 100644 --- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs +++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs @@ -1,12 +1,20 @@ // Test LVI ret hardening on generic rust code +//@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --crate-type staticlib -//@ only-x86_64-fortanix-unknown-sgx +//@ compile-flags: --target x86_64-fortanix-unknown-sgx +//@ needs-llvm-components: x86 + +#![feature(no_core, lang_items, f16)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; #[no_mangle] pub extern "C" fn myret() {} -// CHECK: myret: +// CHECK-LABEL: myret: // CHECK: popq [[REGISTER:%[a-z]+]] // CHECK-NEXT: lfence // CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs index a729df8e166..215fb4b804a 100644 --- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs +++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs @@ -1,13 +1,22 @@ // Test LVI load hardening on SGX inline assembly code +//@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --crate-type staticlib -//@ only-x86_64-fortanix-unknown-sgx +//@ compile-flags: --target x86_64-fortanix-unknown-sgx +//@ needs-llvm-components: x86 -use std::arch::asm; +#![feature(no_core, lang_items, f16)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; #[no_mangle] pub extern "C" fn get(ptr: *const u64) -> u64 { + // CHECK-LABEL: get + // CHECK: movq + // CHECK-NEXT: lfence let value: u64; unsafe { asm!("mov {}, [{}]", @@ -17,18 +26,13 @@ pub extern "C" fn get(ptr: *const u64) -> u64 { value } -// CHECK: get -// CHECK: movq -// CHECK-NEXT: lfence - #[no_mangle] pub extern "C" fn myret() { + // CHECK-LABEL: myret + // CHECK: shlq $0, (%rsp) + // CHECK-NEXT: lfence + // CHECK-NEXT: retq unsafe { asm!("ret"); } } - -// CHECK: myret -// CHECK: shlq $0, (%rsp) -// CHECK-NEXT: lfence -// CHECK-NEXT: retq diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 109a41d1ef9..9bff257e063 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -9,10 +9,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), @@ -30,10 +26,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff new file mode 100644 index 00000000000..52832e73905 --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff @@ -0,0 +1,15 @@ +- // MIR for `cannot_opt_generic` before RemoveUnneededDrops ++ // MIR for `cannot_opt_generic` after RemoveUnneededDrops + + fn cannot_opt_generic(_1: T) -> () { + let mut _0: (); + + bb0: { + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff deleted file mode 100644 index 0c73602bec8..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `cannot_opt_generic` before RemoveUnneededDrops -+ // MIR for `cannot_opt_generic` after RemoveUnneededDrops - - fn cannot_opt_generic(_1: T) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: T; - scope 1 (inlined std::mem::drop::<T>) { - } - - bb0: { - nop; - StorageLive(_3); - _3 = move _1; - drop(_3) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_3); - nop; - nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff deleted file mode 100644 index 59cce9fbcdd..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff +++ /dev/null @@ -1,30 +0,0 @@ -- // MIR for `cannot_opt_generic` before RemoveUnneededDrops -+ // MIR for `cannot_opt_generic` after RemoveUnneededDrops - - fn cannot_opt_generic(_1: T) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: T; - scope 1 (inlined std::mem::drop::<T>) { - } - - bb0: { - nop; - StorageLive(_3); - _3 = move _1; - drop(_3) -> [return: bb2, unwind: bb1]; - } - - bb1 (cleanup): { - resume; - } - - bb2: { - StorageDead(_3); - nop; - nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff new file mode 100644 index 00000000000..3d67cada5dd --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff @@ -0,0 +1,15 @@ +- // MIR for `dont_opt` before RemoveUnneededDrops ++ // MIR for `dont_opt` after RemoveUnneededDrops + + fn dont_opt(_1: Vec<bool>) -> () { + let mut _0: (); + + bb0: { + drop(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff deleted file mode 100644 index 428b366b5a6..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `dont_opt` before RemoveUnneededDrops -+ // MIR for `dont_opt` after RemoveUnneededDrops - - fn dont_opt(_1: Vec<bool>) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: std::vec::Vec<bool>; - scope 1 (inlined std::mem::drop::<Vec<bool>>) { - } - - bb0: { - nop; - StorageLive(_3); - _3 = move _1; - drop(_3) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_3); - nop; - nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff deleted file mode 100644 index 445c1f82a96..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff +++ /dev/null @@ -1,30 +0,0 @@ -- // MIR for `dont_opt` before RemoveUnneededDrops -+ // MIR for `dont_opt` after RemoveUnneededDrops - - fn dont_opt(_1: Vec<bool>) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: std::vec::Vec<bool>; - scope 1 (inlined std::mem::drop::<Vec<bool>>) { - } - - bb0: { - nop; - StorageLive(_3); - _3 = move _1; - drop(_3) -> [return: bb2, unwind: bb1]; - } - - bb1 (cleanup): { - resume; - } - - bb2: { - StorageDead(_3); - nop; - nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff new file mode 100644 index 00000000000..cb7e58ca1a1 --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff @@ -0,0 +1,15 @@ +- // MIR for `opt` before RemoveUnneededDrops ++ // MIR for `opt` after RemoveUnneededDrops + + fn opt(_1: bool) -> () { + let mut _0: (); + + bb0: { +- drop(_1) -> [return: bb1, unwind unreachable]; +- } +- +- bb1: { + return; + } + } + diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff deleted file mode 100644 index 01eb6d4901f..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `opt` before RemoveUnneededDrops -+ // MIR for `opt` after RemoveUnneededDrops - - fn opt(_1: bool) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: bool; - scope 1 (inlined std::mem::drop::<bool>) { - } - - bb0: { -- nop; - StorageLive(_3); - _3 = copy _1; -- drop(_3) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { - StorageDead(_3); -- nop; -- nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff deleted file mode 100644 index c2c3cb76e83..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `opt` before RemoveUnneededDrops -+ // MIR for `opt` after RemoveUnneededDrops - - fn opt(_1: bool) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: bool; - scope 1 (inlined std::mem::drop::<bool>) { - } - - bb0: { -- nop; - StorageLive(_3); - _3 = copy _1; -- drop(_3) -> [return: bb1, unwind continue]; -- } -- -- bb1: { - StorageDead(_3); -- nop; -- nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff new file mode 100644 index 00000000000..1e166eee9fb --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff @@ -0,0 +1,15 @@ +- // MIR for `opt_generic_copy` before RemoveUnneededDrops ++ // MIR for `opt_generic_copy` after RemoveUnneededDrops + + fn opt_generic_copy(_1: T) -> () { + let mut _0: (); + + bb0: { +- drop(_1) -> [return: bb1, unwind unreachable]; +- } +- +- bb1: { + return; + } + } + diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff deleted file mode 100644 index a82ede6196e..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `opt_generic_copy` before RemoveUnneededDrops -+ // MIR for `opt_generic_copy` after RemoveUnneededDrops - - fn opt_generic_copy(_1: T) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: T; - scope 1 (inlined std::mem::drop::<T>) { - } - - bb0: { -- nop; - StorageLive(_3); - _3 = copy _1; -- drop(_3) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { - StorageDead(_3); -- nop; -- nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff deleted file mode 100644 index 6e7c9ead740..00000000000 --- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `opt_generic_copy` before RemoveUnneededDrops -+ // MIR for `opt_generic_copy` after RemoveUnneededDrops - - fn opt_generic_copy(_1: T) -> () { - debug x => _1; - let mut _0: (); - let _2: (); - let mut _3: T; - scope 1 (inlined std::mem::drop::<T>) { - } - - bb0: { -- nop; - StorageLive(_3); - _3 = copy _1; -- drop(_3) -> [return: bb1, unwind continue]; -- } -- -- bb1: { - StorageDead(_3); -- nop; -- nop; - return; - } - } - diff --git a/tests/mir-opt/remove_unneeded_drops.rs b/tests/mir-opt/remove_unneeded_drops.rs index cad79e0aa0c..49dc611838e 100644 --- a/tests/mir-opt/remove_unneeded_drops.rs +++ b/tests/mir-opt/remove_unneeded_drops.rs @@ -1,28 +1,56 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ test-mir-pass: RemoveUnneededDrops + +#![feature(custom_mir, core_intrinsics)] +use std::intrinsics::mir::*; + // EMIT_MIR remove_unneeded_drops.opt.RemoveUnneededDrops.diff +#[custom_mir(dialect = "runtime")] fn opt(x: bool) { - drop(x); + // CHECK-LABEL: fn opt( + // CHECK-NOT: drop( + mir! { + { Drop(x, ReturnTo(bb1), UnwindUnreachable()) } + bb1 = { Return() } + } } // EMIT_MIR remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff +#[custom_mir(dialect = "runtime")] fn dont_opt(x: Vec<bool>) { - drop(x); + // CHECK-LABEL: fn dont_opt( + // CHECK: drop( + mir! { + { Drop(x, ReturnTo(bb1), UnwindUnreachable()) } + bb1 = { Return() } + } } // EMIT_MIR remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff +#[custom_mir(dialect = "runtime")] fn opt_generic_copy<T: Copy>(x: T) { - drop(x); + // CHECK-LABEL: fn opt_generic_copy( + // CHECK-NOT: drop( + mir! { + { Drop(x, ReturnTo(bb1), UnwindUnreachable()) } + bb1 = { Return() } + } } // EMIT_MIR remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff // since the pass is not running on monomorphisized code, // we can't (but probably should) optimize this +#[custom_mir(dialect = "runtime")] fn cannot_opt_generic<T>(x: T) { - drop(x); + // CHECK-LABEL: fn cannot_opt_generic( + // CHECK: drop( + mir! { + { Drop(x, ReturnTo(bb1), UnwindUnreachable()) } + bb1 = { Return() } + } } fn main() { + // CHECK-LABEL: fn main( opt(true); opt_generic_copy(42); cannot_opt_generic(42); diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs index e58762aeb6d..89754cdaf90 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs @@ -13,42 +13,56 @@ //@ only-x86_64-fortanix-unknown-sgx -use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target}; +use run_make_support::{ + cargo, cwd, llvm_filecheck, llvm_objdump, regex, run, set_current_dir, target, +}; fn main() { - let main_dir = cwd(); - set_current_dir("enclave"); - // HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. - // These come from the top-level Rust workspace, that this crate is not a - // member of, but Cargo tries to load the workspace `Cargo.toml` anyway. - cmd("cargo") - .env("RUSTC_BOOTSTRAP", "1") + cargo() .arg("-v") - .arg("run") + .arg("build") .arg("--target") .arg(target()) + .current_dir("enclave") + .env("CC_x86_64_fortanix_unknown_sgx", "clang") + .env( + "CFLAGS_x86_64_fortanix_unknown_sgx", + "-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening", + ) + .env("CXX_x86_64_fortanix_unknown_sgx", "clang++") + .env( + "CXXFLAGS_x86_64_fortanix_unknown_sgx", + "-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening", + ) .run(); - set_current_dir(&main_dir); - // Rust has various ways of adding code to a binary: + + // Rust has several ways of including machine code into a binary: + // // - Rust code // - Inline assembly // - Global assembly // - C/C++ code compiled as part of Rust crates - // For those different kinds, we do have very small code examples that should be - // mitigated in some way. Mostly we check that ret instructions should no longer be present. + // + // For each of those, check that the mitigations are applied. Mostly we check + // that ret instructions are no longer present. + + // Check that normal rust code has the right mitigations. check("unw_getcontext", "unw_getcontext.checks"); check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks"); check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks"); + // Check that rust global assembly has the right mitigations. check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks"); + // Check that C code compiled using the `cc` crate has the right mitigations. check("cc_plus_one_c", "cc_plus_one_c.checks"); check("cc_plus_one_c_asm", "cc_plus_one_c_asm.checks"); check("cc_plus_one_cxx", "cc_plus_one_cxx.checks"); check("cc_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks"); check("cc_plus_one_asm", "cc_plus_one_asm.checks"); + // Check that C++ code compiled using the `cc` crate has the right mitigations. check("cmake_plus_one_c", "cmake_plus_one_c.checks"); check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks"); check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks"); @@ -71,8 +85,7 @@ fn check(func_re: &str, mut checks: &str) { .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave") .args(&["--demangle", &format!("--disassemble-symbols={func}")]) .run() - .stdout_utf8(); - let dump = dump.as_bytes(); + .stdout(); // Unique case, must succeed at one of two possible tests. // This is because frame pointers are optional, and them being enabled requires diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs index 1174e16dd53..cb277d529ce 100644 --- a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs +++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs @@ -2,67 +2,67 @@ //@ normalize-stderr: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL" //! [struct@m!()] //~ WARN: unmatched disambiguator `struct` and suffix `!()` -//! [struct@m!{}] +//! [struct@m!{}] //~ WARN: unmatched disambiguator `struct` and suffix `!{}` //! [struct@m![]] //! [struct@f()] //~ WARN: unmatched disambiguator `struct` and suffix `()` //! [struct@m!] //~ WARN: unmatched disambiguator `struct` and suffix `!` //! //! [enum@m!()] //~ WARN: unmatched disambiguator `enum` and suffix `!()` -//! [enum@m!{}] +//! [enum@m!{}] //~ WARN: unmatched disambiguator `enum` and suffix `!{}` //! [enum@m![]] //! [enum@f()] //~ WARN: unmatched disambiguator `enum` and suffix `()` //! [enum@m!] //~ WARN: unmatched disambiguator `enum` and suffix `!` //! //! [trait@m!()] //~ WARN: unmatched disambiguator `trait` and suffix `!()` -//! [trait@m!{}] +//! [trait@m!{}] //~ WARN: unmatched disambiguator `trait` and suffix `!{}` //! [trait@m![]] //! [trait@f()] //~ WARN: unmatched disambiguator `trait` and suffix `()` //! [trait@m!] //~ WARN: unmatched disambiguator `trait` and suffix `!` //! //! [module@m!()] //~ WARN: unmatched disambiguator `module` and suffix `!()` -//! [module@m!{}] +//! [module@m!{}] //~ WARN: unmatched disambiguator `module` and suffix `!{}` //! [module@m![]] //! [module@f()] //~ WARN: unmatched disambiguator `module` and suffix `()` //! [module@m!] //~ WARN: unmatched disambiguator `module` and suffix `!` //! //! [mod@m!()] //~ WARN: unmatched disambiguator `mod` and suffix `!()` -//! [mod@m!{}] +//! [mod@m!{}] //~ WARN: unmatched disambiguator `mod` and suffix `!{}` //! [mod@m![]] //! [mod@f()] //~ WARN: unmatched disambiguator `mod` and suffix `()` //! [mod@m!] //~ WARN: unmatched disambiguator `mod` and suffix `!` //! //! [const@m!()] //~ WARN: unmatched disambiguator `const` and suffix `!()` -//! [const@m!{}] +//! [const@m!{}] //~ WARN: unmatched disambiguator `const` and suffix `!{}` //! [const@m![]] //! [const@f()] //~ WARN: incompatible link kind for `f` //! [const@m!] //~ WARN: unmatched disambiguator `const` and suffix `!` //! //! [constant@m!()] //~ WARN: unmatched disambiguator `constant` and suffix `!()` -//! [constant@m!{}] +//! [constant@m!{}] //~ WARN: unmatched disambiguator `constant` and suffix `!{}` //! [constant@m![]] //! [constant@f()] //~ WARN: incompatible link kind for `f` //! [constant@m!] //~ WARN: unmatched disambiguator `constant` and suffix `!` //! //! [static@m!()] //~ WARN: unmatched disambiguator `static` and suffix `!()` -//! [static@m!{}] +//! [static@m!{}] //~ WARN: unmatched disambiguator `static` and suffix `!{}` //! [static@m![]] //! [static@f()] //~ WARN: incompatible link kind for `f` //! [static@m!] //~ WARN: unmatched disambiguator `static` and suffix `!` //! //! [function@m!()] //~ WARN: unmatched disambiguator `function` and suffix `!()` -//! [function@m!{}] +//! [function@m!{}] //~ WARN: unmatched disambiguator `function` and suffix `!{}` //! [function@m![]] //! [function@f()] //! [function@m!] //~ WARN: unmatched disambiguator `function` and suffix `!` //! //! [fn@m!()] //~ WARN: unmatched disambiguator `fn` and suffix `!()` -//! [fn@m!{}] +//! [fn@m!{}] //~ WARN: unmatched disambiguator `fn` and suffix `!{}` //! [fn@m![]] //! [fn@f()] //! [fn@m!] //~ WARN: unmatched disambiguator `fn` and suffix `!` //! //! [method@m!()] //~ WARN: unmatched disambiguator `method` and suffix `!()` -//! [method@m!{}] +//! [method@m!{}] //~ WARN: unmatched disambiguator `method` and suffix `!{}` //! [method@m![]] //! [method@f()] //! [method@m!] //~ WARN: unmatched disambiguator `method` and suffix `!` @@ -74,13 +74,13 @@ //! [derive@m!] //~ WARN: incompatible link kind for `m` //! //! [type@m!()] //~ WARN: unmatched disambiguator `type` and suffix `!()` -//! [type@m!{}] +//! [type@m!{}] //~ WARN: unmatched disambiguator `type` and suffix `!{}` //! [type@m![]] //! [type@f()] //~ WARN: unmatched disambiguator `type` and suffix `()` //! [type@m!] //~ WARN: unmatched disambiguator `type` and suffix `!` //! //! [value@m!()] //~ WARN: unmatched disambiguator `value` and suffix `!()` -//! [value@m!{}] +//! [value@m!{}] //~ WARN: unmatched disambiguator `value` and suffix `!{}` //! [value@m![]] //! [value@f()] //! [value@m!] //~ WARN: unmatched disambiguator `value` and suffix `!` @@ -92,13 +92,13 @@ //! [macro@m!] //! //! [prim@m!()] //~ WARN: unmatched disambiguator `prim` and suffix `!()` -//! [prim@m!{}] +//! [prim@m!{}] //~ WARN: unmatched disambiguator `prim` and suffix `!{}` //! [prim@m![]] //! [prim@f()] //~ WARN: unmatched disambiguator `prim` and suffix `()` //! [prim@m!] //~ WARN: unmatched disambiguator `prim` and suffix `!` //! //! [primitive@m!()] //~ WARN: unmatched disambiguator `primitive` and suffix `!()` -//! [primitive@m!{}] +//! [primitive@m!{}] //~ WARN: unmatched disambiguator `primitive` and suffix `!{}` //! [primitive@m![]] //! [primitive@f()] //~ WARN: unmatched disambiguator `primitive` and suffix `()` //! [primitive@m!] //~ WARN: unmatched disambiguator `primitive` and suffix `!` diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr index f4e40a48873..18403385968 100644 --- a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr +++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr @@ -7,6 +7,14 @@ LL | //! [struct@m!()] = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default +warning: unmatched disambiguator `struct` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:5:6 + | +LL | //! [struct@m!{}] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `struct` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:7:6 | @@ -31,6 +39,14 @@ LL | //! [enum@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `enum` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:11:6 + | +LL | //! [enum@m!{}] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `enum` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:13:6 | @@ -55,6 +71,14 @@ LL | //! [trait@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `trait` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:17:6 + | +LL | //! [trait@m!{}] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `trait` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:19:6 | @@ -79,6 +103,14 @@ LL | //! [module@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `module` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:23:6 + | +LL | //! [module@m!{}] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `module` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:25:6 | @@ -103,6 +135,14 @@ LL | //! [mod@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `mod` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:29:6 + | +LL | //! [mod@m!{}] + | ^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `mod` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:31:6 | @@ -127,6 +167,14 @@ LL | //! [const@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `const` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:35:6 + | +LL | //! [const@m!{}] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: incompatible link kind for `f` --> $DIR/disambiguator-endswith-named-suffix.rs:37:6 | @@ -155,6 +203,14 @@ LL | //! [constant@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `constant` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:41:6 + | +LL | //! [constant@m!{}] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: incompatible link kind for `f` --> $DIR/disambiguator-endswith-named-suffix.rs:43:6 | @@ -183,6 +239,14 @@ LL | //! [static@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `static` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:47:6 + | +LL | //! [static@m!{}] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: incompatible link kind for `f` --> $DIR/disambiguator-endswith-named-suffix.rs:49:6 | @@ -211,6 +275,14 @@ LL | //! [function@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `function` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:53:6 + | +LL | //! [function@m!{}] + | ^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `function` and suffix `!` --> $DIR/disambiguator-endswith-named-suffix.rs:56:6 | @@ -227,6 +299,14 @@ LL | //! [fn@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `fn` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:59:6 + | +LL | //! [fn@m!{}] + | ^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `fn` and suffix `!` --> $DIR/disambiguator-endswith-named-suffix.rs:62:6 | @@ -243,6 +323,14 @@ LL | //! [method@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `method` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:65:6 + | +LL | //! [method@m!{}] + | ^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `method` and suffix `!` --> $DIR/disambiguator-endswith-named-suffix.rs:68:6 | @@ -303,6 +391,14 @@ LL | //! [type@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `type` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:77:6 + | +LL | //! [type@m!{}] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `type` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:79:6 | @@ -327,6 +423,14 @@ LL | //! [value@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `value` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:83:6 + | +LL | //! [value@m!{}] + | ^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `value` and suffix `!` --> $DIR/disambiguator-endswith-named-suffix.rs:86:6 | @@ -351,6 +455,14 @@ LL | //! [prim@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `prim` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:95:6 + | +LL | //! [prim@m!{}] + | ^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `prim` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:97:6 | @@ -375,6 +487,14 @@ LL | //! [primitive@m!()] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators +warning: unmatched disambiguator `primitive` and suffix `!{}` + --> $DIR/disambiguator-endswith-named-suffix.rs:101:6 + | +LL | //! [primitive@m!{}] + | ^^^^^^^^^ + | + = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators + warning: unmatched disambiguator `primitive` and suffix `()` --> $DIR/disambiguator-endswith-named-suffix.rs:103:6 | @@ -391,5 +511,5 @@ LL | //! [primitive@m!] | = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators -warning: 46 warnings emitted +warning: 61 warnings emitted diff --git a/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs b/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs new file mode 100644 index 00000000000..c24a848d898 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs @@ -0,0 +1,15 @@ +#![no_std] +#![deny(rustdoc::broken_intra_doc_links)] + +// regression test for https://github.com/rust-lang/rust/issues/54191 + +/// this is not a link to [`example.com`] //~ERROR unresolved link +/// +/// this link [`has spaces in it`]. +/// +/// attempted link to method: [`Foo.bar()`] //~ERROR unresolved link +/// +/// classic broken intra-doc link: [`Bar`] //~ERROR unresolved link +/// +/// no backticks, so we let this one slide: [Foo.bar()] +pub struct Foo; diff --git a/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr b/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr new file mode 100644 index 00000000000..9533792b35b --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr @@ -0,0 +1,31 @@ +error: unresolved link to `example.com` + --> $DIR/bad-intra-doc.rs:6:29 + | +LL | /// this is not a link to [`example.com`] + | ^^^^^^^^^^^ no item named `example.com` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` +note: the lint level is defined here + --> $DIR/bad-intra-doc.rs:2:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unresolved link to `Foo.bar` + --> $DIR/bad-intra-doc.rs:10:33 + | +LL | /// attempted link to method: [`Foo.bar()`] + | ^^^^^^^^^ no item named `Foo.bar` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `Bar` + --> $DIR/bad-intra-doc.rs:12:38 + | +LL | /// classic broken intra-doc link: [`Bar`] + | ^^^ no item named `Bar` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: aborting due to 3 previous errors + diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.rs b/tests/rustdoc-ui/intra-doc/weird-syntax.rs index d2a922b2b62..1c5977b1bc3 100644 --- a/tests/rustdoc-ui/intra-doc/weird-syntax.rs +++ b/tests/rustdoc-ui/intra-doc/weird-syntax.rs @@ -65,7 +65,7 @@ pub struct XLinkToCloneWithStartSpace; /// [x][struct@Clone ] //~ERROR link pub struct XLinkToCloneWithEndSpace; -/// [x][Clone\(\)] not URL-shaped enough +/// [x][Clone\(\)] //~ERROR link pub struct XLinkToCloneWithEscapedParens; /// [x][`Clone`] not URL-shaped enough diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr index ad813f0f9b6..7f2fc1fe625 100644 --- a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr +++ b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr @@ -123,6 +123,14 @@ LL - /// [x][struct@Clone ] LL + /// [x][trait@Clone ] | +error: unresolved link to `Clone\(\)` + --> $DIR/weird-syntax.rs:68:9 + | +LL | /// [x][Clone\(\)] + | ^^^^^^^^^ no item named `Clone\(\)` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + error: unresolved link to `Clone` --> $DIR/weird-syntax.rs:74:9 | @@ -299,5 +307,5 @@ LL | /// - [`SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER`]: the | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs index 4f4590d45fc..81cd6c73d1c 100644 --- a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs +++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs @@ -1,18 +1,24 @@ //@ check-pass -/// [`…foo`] [`…bar`] [`Err`] +/// [`…foo`] //~ WARN: unresolved link +/// [`…bar`] //~ WARN: unresolved link +/// [`Err`] pub struct Broken {} -/// [`…`] [`…`] [`Err`] +/// [`…`] //~ WARN: unresolved link +/// [`…`] //~ WARN: unresolved link +/// [`Err`] pub struct Broken2 {} -/// [`…`][…] [`…`][…] [`Err`] +/// [`…`][…] //~ WARN: unresolved link +/// [`…`][…] //~ WARN: unresolved link +/// [`Err`] pub struct Broken3 {} /// […………………………][Broken3] pub struct Broken4 {} -/// [Broken3][…………………………] +/// [Broken3][…………………………] //~ WARN: unresolved link pub struct Broken5 {} pub struct Err; diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr new file mode 100644 index 00000000000..0a5ff68b908 --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr @@ -0,0 +1,59 @@ +warning: unresolved link to `…foo` + --> $DIR/redundant_explicit_links-utf8.rs:3:7 + | +LL | /// [`…foo`] + | ^^^^ no item named `…foo` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: unresolved link to `…bar` + --> $DIR/redundant_explicit_links-utf8.rs:4:7 + | +LL | /// [`…bar`] + | ^^^^ no item named `…bar` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `…` + --> $DIR/redundant_explicit_links-utf8.rs:8:7 + | +LL | /// [`…`] + | ^ no item named `…` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `…` + --> $DIR/redundant_explicit_links-utf8.rs:9:7 + | +LL | /// [`…`] + | ^ no item named `…` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `…` + --> $DIR/redundant_explicit_links-utf8.rs:13:11 + | +LL | /// [`…`][…] + | ^ no item named `…` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `…` + --> $DIR/redundant_explicit_links-utf8.rs:14:11 + | +LL | /// [`…`][…] + | ^ no item named `…` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `…………………………` + --> $DIR/redundant_explicit_links-utf8.rs:21:15 + | +LL | /// [Broken3][…………………………] + | ^^^^^^^^^^ no item named `…………………………` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: 7 warnings emitted + diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs index 841533814c3..bf9b81077f3 100644 --- a/tests/rustdoc/attribute-rendering.rs +++ b/tests/rustdoc/attribute-rendering.rs @@ -1,7 +1,7 @@ #![crate_name = "foo"] //@ has 'foo/fn.f.html' -//@ has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()' -#[export_name = "\ -f"] +//@ has - //*[@'class="rust item-decl"]' '#[unsafe(export_name = "f")] pub fn f()' +#[unsafe(export_name = "\ +f")] pub fn f() {} diff --git a/tests/rustdoc/attributes-2021-edition.rs b/tests/rustdoc/attributes-2021-edition.rs new file mode 100644 index 00000000000..b5028d8c852 --- /dev/null +++ b/tests/rustdoc/attributes-2021-edition.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 +#![crate_name = "foo"] + +//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' +#[no_mangle] +pub extern "C" fn f() {} + +//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]' +#[export_name = "bar"] +pub extern "C" fn g() {} + +//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]' +#[link_section = ".text"] +pub extern "C" fn example() {} diff --git a/tests/rustdoc/attributes-re-export-2021-edition.rs b/tests/rustdoc/attributes-re-export-2021-edition.rs new file mode 100644 index 00000000000..04ee6c273dd --- /dev/null +++ b/tests/rustdoc/attributes-re-export-2021-edition.rs @@ -0,0 +1,13 @@ +// Tests that attributes are correctly copied onto a re-exported item. +//@ edition:2024 +#![crate_name = "re_export"] + +//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' +pub use thingymod::thingy as thingy2; + +mod thingymod { + #[unsafe(no_mangle)] + pub fn thingy() { + + } +} diff --git a/tests/rustdoc/attributes-re-export.rs b/tests/rustdoc/attributes-re-export.rs index 458826ea8a3..820276f83c0 100644 --- a/tests/rustdoc/attributes-re-export.rs +++ b/tests/rustdoc/attributes-re-export.rs @@ -2,7 +2,7 @@ //@ edition:2021 #![crate_name = "re_export"] -//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[no_mangle]' +//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' pub use thingymod::thingy as thingy2; mod thingymod { diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs index e34468a88b1..34487a89127 100644 --- a/tests/rustdoc/attributes.rs +++ b/tests/rustdoc/attributes.rs @@ -1,13 +1,18 @@ +//@ edition: 2024 #![crate_name = "foo"] -//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]' -#[no_mangle] +//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' +#[unsafe(no_mangle)] pub extern "C" fn f() {} -//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]' -#[export_name = "bar"] +//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]' +#[unsafe(export_name = "bar")] pub extern "C" fn g() {} +//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]' +#[unsafe(link_section = ".text")] +pub extern "C" fn example() {} + //@ has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; diff --git a/tests/rustdoc/reexport/reexport-attrs.rs b/tests/rustdoc/reexport/reexport-attrs.rs index 0ec645841f0..aec0a11c0c6 100644 --- a/tests/rustdoc/reexport/reexport-attrs.rs +++ b/tests/rustdoc/reexport/reexport-attrs.rs @@ -4,13 +4,13 @@ extern crate reexports_attrs; -//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[no_mangle]' +//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' pub use reexports_attrs::f0; -//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[link_section = ".here"]' +//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".here")]' pub use reexports_attrs::f1; -//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[export_name = "f2export"]' +//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "f2export")]' pub use reexports_attrs::f2; //@ has 'foo/enum.T0.html' '//pre[@class="rust item-decl"]' '#[repr(u8)]' diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 58a5b0b79c4..a507fa69760 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0}<?16t> upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0}<?15t> upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0}<?16t> upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0}<?15t> upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr index d1f2d9a0753..d1c88101618 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr @@ -21,30 +21,6 @@ LL | Box::new(async { new(|| async { f().await }).await }) = help: consider pinning your async block and casting it to a trait object = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index bc181de8d92..c11332fe7d8 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -4,6 +4,7 @@ use std::future::Future; fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { //~^ ERROR future cannot be sent between threads safely async { (ty, ty1) } + //~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 8de6a825042..07fd20cdd77 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,4 +1,25 @@ error: future cannot be sent between threads safely + --> $DIR/issue-70818.rs:6:5 + | +LL | async { (ty, ty1) } + | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> $DIR/issue-70818.rs:6:18 + | +LL | async { (ty, ty1) } + | ^^^ has type `U` which is not `Send` +note: required by a bound in an opaque type + --> $DIR/issue-70818.rs:4:69 + | +LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { + | ^^^^ +help: consider restricting type parameter `U` with trait `Send` + | +LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { + | +++++++++++++++++++ + +error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { @@ -14,5 +35,5 @@ help: consider restricting type parameter `U` with trait `Send` LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { | +++++++++++++++++++ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index 6385a8c975e..c71801dcfc8 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>` + = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<dyn Future<Output = ()> + Send>>` help: consider further restricting type parameter `T` with trait `Sync` | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/tests/ui/cfg/both-true-false.stderr b/tests/ui/cfg/both-true-false.stderr index 1526cc2b707..1a7c509aec0 100644 --- a/tests/ui/cfg/both-true-false.stderr +++ b/tests/ui/cfg/both-true-false.stderr @@ -3,6 +3,22 @@ error[E0425]: cannot find function `foo` in this scope | LL | foo(); | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/both-true-false.rs:6:4 + | +LL | #[cfg(false)] + | ----- the item is gated here +LL | #[cfg(true)] +LL | fn foo() {} + | ^^^ +note: found an item that was configured out + --> $DIR/both-true-false.rs:10:4 + | +LL | #[cfg(false)] + | ----- the item is gated here +LL | fn foo() {} + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cfg/cfg-version/syntax.stderr b/tests/ui/cfg/cfg-version/syntax.stderr index 188f6d7aa5d..34ddfff3e8e 100644 --- a/tests/ui/cfg/cfg-version/syntax.stderr +++ b/tests/ui/cfg/cfg-version/syntax.stderr @@ -128,60 +128,150 @@ error[E0425]: cannot find function `key_value_form` in this scope | LL | key_value_form(); | ^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:32:4 + | +LL | #[cfg(version = "1.43")] + | ---------------- the item is gated behind the `1.43` feature +LL | +LL | fn key_value_form() {} + | ^^^^^^^^^^^^^^ error[E0425]: cannot find function `not_numbers_or_periods` in this scope --> $DIR/syntax.rs:143:5 | LL | not_numbers_or_periods(); | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:53:4 + | +LL | #[cfg(version("foo"))] + | ------- the item is gated here +LL | +LL | fn not_numbers_or_periods() {} + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `complex_semver_with_metadata` in this scope --> $DIR/syntax.rs:144:5 | LL | complex_semver_with_metadata(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:57:4 + | +LL | #[cfg(version("1.20.0-stable"))] + | ----------------- the item is gated here +LL | +LL | fn complex_semver_with_metadata() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `invalid_major_only` in this scope --> $DIR/syntax.rs:145:5 | LL | invalid_major_only(); | ^^^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:80:4 + | +LL | #[cfg(version("1"))] + | ----- the item is gated here +LL | +LL | fn invalid_major_only() {} + | ^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `invalid_major_only_zero` in this scope --> $DIR/syntax.rs:146:5 | LL | invalid_major_only_zero(); | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:84:4 + | +LL | #[cfg(version("0"))] + | ----- the item is gated here +LL | +LL | fn invalid_major_only_zero() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `invalid_major_only_negative` in this scope --> $DIR/syntax.rs:147:5 | LL | invalid_major_only_negative(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:97:4 + | +LL | #[cfg(version("-1"))] + | ------ the item is gated here +LL | +LL | fn invalid_major_only_negative() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `exceed_u16_major` in this scope --> $DIR/syntax.rs:148:5 | LL | exceed_u16_major(); | ^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:103:4 + | +LL | #[cfg(version("65536"))] + | --------- the item is gated here +LL | +LL | fn exceed_u16_major() {} + | ^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `exceed_u16_minor` in this scope --> $DIR/syntax.rs:149:5 | LL | exceed_u16_minor(); | ^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:107:4 + | +LL | #[cfg(version("1.65536.0"))] + | ------------- the item is gated here +LL | +LL | fn exceed_u16_minor() {} + | ^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `exceed_u16_patch` in this scope --> $DIR/syntax.rs:150:5 | LL | exceed_u16_patch(); | ^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:111:4 + | +LL | #[cfg(version("1.0.65536"))] + | ------------- the item is gated here +LL | +LL | fn exceed_u16_patch() {} + | ^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `exceed_u16_mixed` in this scope --> $DIR/syntax.rs:151:5 | LL | exceed_u16_mixed(); | ^^^^^^^^^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/syntax.rs:115:4 + | +LL | #[cfg(version("65536.0.65536"))] + | ----------------- the item is gated here +LL | +LL | fn exceed_u16_mixed() {} + | ^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors; 14 warnings emitted diff --git a/tests/ui/cfg/cmdline-false.stderr b/tests/ui/cfg/cmdline-false.stderr index 5f57c754c40..3d486803821 100644 --- a/tests/ui/cfg/cmdline-false.stderr +++ b/tests/ui/cfg/cmdline-false.stderr @@ -3,6 +3,14 @@ error[E0425]: cannot find function `foo` in this scope | LL | foo(); | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/cmdline-false.rs:5:4 + | +LL | #[cfg(false)] + | ----- the item is gated here +LL | fn foo() {} + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cfg/diagnostics-cross-crate.rs b/tests/ui/cfg/diagnostics-cross-crate.rs index 00ac7e2fd08..f959332c817 100644 --- a/tests/ui/cfg/diagnostics-cross-crate.rs +++ b/tests/ui/cfg/diagnostics-cross-crate.rs @@ -11,24 +11,20 @@ fn main() { cfged_out::inner::uwu(); //~ ERROR cannot find function //~^ NOTE found an item that was configured out //~| NOTE not found in `cfged_out::inner` - //~| NOTE the item is gated here // The module isn't found - we would like to get a diagnostic, but currently don't due to // the awkward way the resolver diagnostics are currently implemented. cfged_out::inner::doesnt_exist::hello(); //~ ERROR failed to resolve //~^ NOTE could not find `doesnt_exist` in `inner` //~| NOTE found an item that was configured out - //~| NOTE the item is gated here // It should find the one in the right module, not the wrong one. cfged_out::inner::right::meow(); //~ ERROR cannot find function //~^ NOTE found an item that was configured out //~| NOTE not found in `cfged_out::inner::right - //~| NOTE the item is gated behind the `what-a-cool-feature` feature // Exists in the crate root - diagnostic. cfged_out::vanished(); //~ ERROR cannot find function //~^ NOTE found an item that was configured out //~| NOTE not found in `cfged_out` - //~| NOTE the item is gated here } diff --git a/tests/ui/cfg/diagnostics-cross-crate.stderr b/tests/ui/cfg/diagnostics-cross-crate.stderr index 155b3db2f42..658e5a442bd 100644 --- a/tests/ui/cfg/diagnostics-cross-crate.stderr +++ b/tests/ui/cfg/diagnostics-cross-crate.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` - --> $DIR/diagnostics-cross-crate.rs:18:23 + --> $DIR/diagnostics-cross-crate.rs:17:23 | LL | cfged_out::inner::doesnt_exist::hello(); | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` @@ -7,13 +7,10 @@ LL | cfged_out::inner::doesnt_exist::hello(); note: found an item that was configured out --> $DIR/auxiliary/cfged_out.rs:6:13 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ -note: the item is gated here - --> $DIR/auxiliary/cfged_out.rs:5:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0425]: cannot find function `uwu` in crate `cfged_out` --> $DIR/diagnostics-cross-crate.rs:7:16 @@ -30,16 +27,13 @@ LL | cfged_out::inner::uwu(); note: found an item that was configured out --> $DIR/auxiliary/cfged_out.rs:3:12 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub fn uwu() {} | ^^^ -note: the item is gated here - --> $DIR/auxiliary/cfged_out.rs:2:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0425]: cannot find function `meow` in module `cfged_out::inner::right` - --> $DIR/diagnostics-cross-crate.rs:24:30 + --> $DIR/diagnostics-cross-crate.rs:22:30 | LL | cfged_out::inner::right::meow(); | ^^^^ not found in `cfged_out::inner::right` @@ -47,16 +41,13 @@ LL | cfged_out::inner::right::meow(); note: found an item that was configured out --> $DIR/auxiliary/cfged_out.rs:17:16 | +LL | #[cfg(feature = "what-a-cool-feature")] + | ------------------------------- the item is gated behind the `what-a-cool-feature` feature LL | pub fn meow() {} | ^^^^ -note: the item is gated behind the `what-a-cool-feature` feature - --> $DIR/auxiliary/cfged_out.rs:16:15 - | -LL | #[cfg(feature = "what-a-cool-feature")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `vanished` in crate `cfged_out` - --> $DIR/diagnostics-cross-crate.rs:30:16 + --> $DIR/diagnostics-cross-crate.rs:27:16 | LL | cfged_out::vanished(); | ^^^^^^^^ not found in `cfged_out` @@ -64,13 +55,10 @@ LL | cfged_out::vanished(); note: found an item that was configured out --> $DIR/auxiliary/cfged_out.rs:22:8 | +LL | #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] + | -------------------------------------------- the item is gated here LL | pub fn vanished() {} | ^^^^^^^^ -note: the item is gated here - --> $DIR/auxiliary/cfged_out.rs:21:7 - | -LL | #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/cfg/diagnostics-reexport-2.stderr b/tests/ui/cfg/diagnostics-reexport-2.stderr index e1f91fcc5d1..713cffce65b 100644 --- a/tests/ui/cfg/diagnostics-reexport-2.stderr +++ b/tests/ui/cfg/diagnostics-reexport-2.stderr @@ -7,13 +7,11 @@ LL | reexport::gated::foo(); note: found an item that was configured out --> $DIR/diagnostics-reexport-2.rs:10:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod gated { | ^^^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport-2.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0433]: failed to resolve: could not find `gated` in `reexport2` --> $DIR/diagnostics-reexport-2.rs:46:16 @@ -24,13 +22,11 @@ LL | reexport2::gated::foo(); note: found an item that was configured out --> $DIR/diagnostics-reexport-2.rs:10:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod gated { | ^^^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport-2.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0433]: failed to resolve: could not find `gated` in `reexport30` --> $DIR/diagnostics-reexport-2.rs:50:17 @@ -41,13 +37,11 @@ LL | reexport30::gated::foo(); note: found an item that was configured out --> $DIR/diagnostics-reexport-2.rs:10:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod gated { | ^^^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport-2.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0433]: failed to resolve: could not find `gated` in `reexport31` --> $DIR/diagnostics-reexport-2.rs:54:17 @@ -58,13 +52,11 @@ LL | reexport31::gated::foo(); note: found an item that was configured out --> $DIR/diagnostics-reexport-2.rs:10:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod gated { | ^^^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport-2.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0433]: failed to resolve: could not find `gated` in `reexport32` --> $DIR/diagnostics-reexport-2.rs:58:17 @@ -75,13 +67,11 @@ LL | reexport32::gated::foo(); note: found an item that was configured out --> $DIR/diagnostics-reexport-2.rs:10:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod gated { | ^^^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport-2.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs index 56fac562238..c6a714fca71 100644 --- a/tests/ui/cfg/diagnostics-reexport.rs +++ b/tests/ui/cfg/diagnostics-reexport.rs @@ -34,7 +34,7 @@ mod b { } fn main() { - // There is no uwu at this path - no diagnostic. + // There is no uwu at this path, but there's one in a cgfd out sub-module, so we mention it. inner::uwu(); //~ ERROR cannot find function //~^ NOTE not found in `inner` } diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr index bf1bbcba7e4..a3a6e13f475 100644 --- a/tests/ui/cfg/diagnostics-reexport.stderr +++ b/tests/ui/cfg/diagnostics-reexport.stderr @@ -7,13 +7,10 @@ LL | pub use a::x; note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:18:12 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub fn x() {} | ^ -note: the item is gated here - --> $DIR/diagnostics-reexport.rs:17:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0432]: unresolved imports `b::x`, `b::y` --> $DIR/diagnostics-reexport.rs:22:13 @@ -26,23 +23,17 @@ LL | pub use b::{x, y}; note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:29:12 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub fn x() {} | ^ -note: the item is gated here - --> $DIR/diagnostics-reexport.rs:28:11 - | -LL | #[cfg(false)] - | ^^^^^ note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:32:12 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub fn y() {} | ^ -note: the item is gated here - --> $DIR/diagnostics-reexport.rs:31:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0425]: cannot find function `uwu` in module `inner` --> $DIR/diagnostics-reexport.rs:38:12 @@ -53,13 +44,10 @@ LL | inner::uwu(); note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:8:20 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub use super::uwu; | ^^^ -note: the item is gated here - --> $DIR/diagnostics-reexport.rs:7:11 - | -LL | #[cfg(false)] - | ^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs index 9153f20b296..29209d5f3ea 100644 --- a/tests/ui/cfg/diagnostics-same-crate.rs +++ b/tests/ui/cfg/diagnostics-same-crate.rs @@ -37,8 +37,8 @@ mod placeholder { //~| NOTE could not find `doesnt_exist` in `inner` } -#[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] -pub fn vanished() {} +#[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] //~ NOTE the item is gated here +pub fn vanished() {} //~ NOTE found an item that was configured out fn main() { // There is no uwu at this path - no diagnostic. @@ -49,8 +49,7 @@ fn main() { inner::uwu(); //~ ERROR cannot find function //~| NOTE not found in `inner` - // The module isn't found - we would like to get a diagnostic, but currently don't due to - // the awkward way the resolver diagnostics are currently implemented. + // The module isn't found - we get a diagnostic. inner::doesnt_exist::hello(); //~ ERROR failed to resolve //~| NOTE could not find `doesnt_exist` in `inner` @@ -58,9 +57,8 @@ fn main() { inner::right::meow(); //~ ERROR cannot find function //~| NOTE not found in `inner::right - // Exists in the crate root - we would generally want a diagnostic, - // but currently don't have one. - // Not that it matters much though, this is highly unlikely to confuse anyone. + // Exists in the crate root - we show a diagnostic because we treat "no module DefId" as "crate + // root DefId". vanished(); //~ ERROR cannot find function //~^ NOTE not found in this scope } diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr index 121f25ca090..a8d789e61d1 100644 --- a/tests/ui/cfg/diagnostics-same-crate.stderr +++ b/tests/ui/cfg/diagnostics-same-crate.stderr @@ -7,13 +7,11 @@ LL | use super::inner::doesnt_exist; note: found an item that was configured out --> $DIR/diagnostics-same-crate.rs:11:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ -note: the item is gated here - --> $DIR/diagnostics-same-crate.rs:8:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0432]: unresolved import `super::inner::doesnt_exist` --> $DIR/diagnostics-same-crate.rs:35:23 @@ -24,16 +22,14 @@ LL | use super::inner::doesnt_exist::hi; note: found an item that was configured out --> $DIR/diagnostics-same-crate.rs:11:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ -note: the item is gated here - --> $DIR/diagnostics-same-crate.rs:8:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` - --> $DIR/diagnostics-same-crate.rs:54:12 + --> $DIR/diagnostics-same-crate.rs:53:12 | LL | inner::doesnt_exist::hello(); | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` @@ -41,13 +37,11 @@ LL | inner::doesnt_exist::hello(); note: found an item that was configured out --> $DIR/diagnostics-same-crate.rs:11:13 | +LL | #[cfg(false)] + | ----- the item is gated here +... LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ -note: the item is gated here - --> $DIR/diagnostics-same-crate.rs:8:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0425]: cannot find function `uwu` in module `inner` --> $DIR/diagnostics-same-crate.rs:49:12 @@ -58,16 +52,13 @@ LL | inner::uwu(); note: found an item that was configured out --> $DIR/diagnostics-same-crate.rs:5:12 | +LL | #[cfg(false)] + | ----- the item is gated here LL | pub fn uwu() {} | ^^^ -note: the item is gated here - --> $DIR/diagnostics-same-crate.rs:4:11 - | -LL | #[cfg(false)] - | ^^^^^ error[E0425]: cannot find function `meow` in module `inner::right` - --> $DIR/diagnostics-same-crate.rs:58:19 + --> $DIR/diagnostics-same-crate.rs:57:19 | LL | inner::right::meow(); | ^^^^ not found in `inner::right` @@ -75,13 +66,10 @@ LL | inner::right::meow(); note: found an item that was configured out --> $DIR/diagnostics-same-crate.rs:26:16 | +LL | #[cfg(feature = "what-a-cool-feature")] + | ------------------------------- the item is gated behind the `what-a-cool-feature` feature LL | pub fn meow() {} | ^^^^ -note: the item is gated behind the `what-a-cool-feature` feature - --> $DIR/diagnostics-same-crate.rs:25:15 - | -LL | #[cfg(feature = "what-a-cool-feature")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in this scope --> $DIR/diagnostics-same-crate.rs:45:5 @@ -90,10 +78,18 @@ LL | uwu(); | ^^^ not found in this scope error[E0425]: cannot find function `vanished` in this scope - --> $DIR/diagnostics-same-crate.rs:64:5 + --> $DIR/diagnostics-same-crate.rs:62:5 | LL | vanished(); | ^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/diagnostics-same-crate.rs:41:8 + | +LL | #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] + | -------------------------------------------- the item is gated here +LL | pub fn vanished() {} + | ^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs index 7618e83a642..c5d86a27d52 100644 --- a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs +++ b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs @@ -10,9 +10,10 @@ //! //! Added in <https://github.com/rust-lang/rust/pull/34216>. -#[cfg_attr(all(), cfg_attr(all(), cfg(false)))] -fn f() {} +#[cfg_attr(all(), cfg_attr(all(), cfg(false)))] //~ NOTE the item is gated here +fn f() {} //~ NOTE found an item that was configured out fn main() { f() //~ ERROR cannot find function `f` in this scope + //~^ NOTE not found in this scope } diff --git a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr index ddb8ea1e13a..3f833bd558b 100644 --- a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr +++ b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr @@ -3,6 +3,14 @@ error[E0425]: cannot find function `f` in this scope | LL | f() | ^ not found in this scope + | +note: found an item that was configured out + --> $DIR/nested-cfg-attr-conditional-compilation.rs:14:4 + | +LL | #[cfg_attr(all(), cfg_attr(all(), cfg(false)))] + | ----- the item is gated here +LL | fn f() {} + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/test-cfg.rs b/tests/ui/conditional-compilation/test-cfg.rs index adbbc309be4..b3fff26a8fd 100644 --- a/tests/ui/conditional-compilation/test-cfg.rs +++ b/tests/ui/conditional-compilation/test-cfg.rs @@ -1,8 +1,10 @@ //@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) #[cfg(all(foo, bar))] // foo AND bar -fn foo() {} +//~^ NOTE the item is gated here +fn foo() {} //~ NOTE found an item that was configured out fn main() { foo(); //~ ERROR cannot find function `foo` in this scope + //~^ NOTE not found in this scope } diff --git a/tests/ui/conditional-compilation/test-cfg.stderr b/tests/ui/conditional-compilation/test-cfg.stderr index 9715f16acc2..379456f74b1 100644 --- a/tests/ui/conditional-compilation/test-cfg.stderr +++ b/tests/ui/conditional-compilation/test-cfg.stderr @@ -1,8 +1,17 @@ error[E0425]: cannot find function `foo` in this scope - --> $DIR/test-cfg.rs:7:5 + --> $DIR/test-cfg.rs:8:5 | LL | foo(); | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/test-cfg.rs:5:4 + | +LL | #[cfg(all(foo, bar))] // foo AND bar + | --- the item is gated here +LL | +LL | fn foo() {} + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs index 2794b167aa2..4e2b26d0295 100644 --- a/tests/ui/coroutine/clone-impl-async.rs +++ b/tests/ui/coroutine/clone-impl-async.rs @@ -9,7 +9,7 @@ use std::future::ready; struct NonClone; -fn main() { +fn local() { let inner_non_clone = async { let non_clone = NonClone; let () = ready(()).await; @@ -34,7 +34,9 @@ fn main() { //~^ ERROR : Copy` is not satisfied check_clone(&maybe_copy_clone); //~^ ERROR : Clone` is not satisfied +} +fn non_local() { let inner_non_clone_fn = the_inner_non_clone_fn(); check_copy(&inner_non_clone_fn); //~^ ERROR : Copy` is not satisfied @@ -69,3 +71,5 @@ async fn the_maybe_copy_clone_fn() {} fn check_copy<T: Copy>(_x: &T) {} fn check_clone<T: Clone>(_x: &T) {} + +fn main() {} diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr index 62bcce2fbcb..319a5ed3d8d 100644 --- a/tests/ui/coroutine/clone-impl-async.stderr +++ b/tests/ui/coroutine/clone-impl-async.stderr @@ -1,167 +1,155 @@ -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:18:16 +error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:41:16 | -LL | check_copy(&inner_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_copy(&inner_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:20:17 +error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:43:17 | -LL | check_clone(&inner_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_clone(&inner_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:27:16 +error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:47:16 | -LL | check_copy(&outer_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_copy(&outer_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:29:17 +error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:49:17 | -LL | check_clone(&outer_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_clone(&outer_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:33:16 +error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:53:16 | -LL | check_copy(&maybe_copy_clone); - | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_copy(&maybe_copy_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:35:17 +error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:55:17 | -LL | check_clone(&maybe_copy_clone); - | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_clone(&maybe_copy_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:39:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:18:5 | -LL | check_copy(&inner_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_copy(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:41:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:20:5 | -LL | check_clone(&inner_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_clone(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:45:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:27:5 | -LL | check_copy(&outer_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_copy(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:47:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:29:5 | -LL | check_clone(&outer_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_clone(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:51:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:33:5 | -LL | check_copy(&maybe_copy_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_copy(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:53:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:35:5 | -LL | check_clone(&maybe_copy_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` - | | - | required by a bound introduced by this call +LL | check_clone(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index 9fb71fd5fd0..4df6b9759c3 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied - --> $DIR/clone-impl-static.rs:14:16 + --> $DIR/clone-impl-static.rs:14:5 | LL | check_copy(&generator); - | ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_copy` --> $DIR/clone-impl-static.rs:20:18 @@ -13,12 +11,10 @@ LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied - --> $DIR/clone-impl-static.rs:16:17 + --> $DIR/clone-impl-static.rs:16:5 | LL | check_clone(&generator); - | ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_clone` --> $DIR/clone-impl-static.rs:21:19 diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs index e528f031d52..9e04e256fc1 100644 --- a/tests/ui/coroutine/clone-impl.rs +++ b/tests/ui/coroutine/clone-impl.rs @@ -42,6 +42,7 @@ fn test3_upvars() { let clonable_0: Vec<u32> = Vec::new(); let gen_clone_0 = #[coroutine] move || { + yield; drop(clonable_0); }; check_copy(&gen_clone_0); diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 714e5aa3d9e..f316902a42d 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -1,59 +1,81 @@ error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` - --> $DIR/clone-impl.rs:47:16 + --> $DIR/clone-impl.rs:48:5 | LL | move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:45:14 + --> $DIR/clone-impl.rs:46:14 | LL | drop(clonable_0); | ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` - --> $DIR/clone-impl.rs:73:16 +error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` + --> $DIR/clone-impl.rs:60:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`, the trait `Copy` is not implemented for `Vec<u32>` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`, the trait `Copy` is not implemented for `Vec<char>` + | +note: coroutine does not implement `Copy` as this value is used across a yield + --> $DIR/clone-impl.rs:57:9 + | +LL | let v = vec!['a']; + | - has type `Vec<char>` which does not implement `Copy` +LL | yield; + | ^^^^^ yield occurs here, with `v` maybe used later +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:92:18 + | +LL | fn check_copy<T: Copy>(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` + --> $DIR/clone-impl.rs:74:5 + | +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` +... +LL | check_copy(&gen_clone_1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`, the trait `Copy` is not implemented for `Vec<u32>` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:71:14 + --> $DIR/clone-impl.rs:72:14 | LL | drop(clonable_1); | ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:85:16 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:86:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Copy` is not implemented for `NonClone` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` @@ -63,22 +85,22 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:87:17 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:88:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Clone` is not implemented for `NonClone` | note: captured value does not implement `Clone` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` note: required by a bound in `check_clone` - --> $DIR/clone-impl.rs:92:19 + --> $DIR/clone-impl.rs:93:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` @@ -88,28 +110,6 @@ LL + #[derive(Clone)] LL | struct NonClone; | -error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` - --> $DIR/clone-impl.rs:59:5 - | -LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` -... -LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`, the trait `Copy` is not implemented for `Vec<char>` - | -note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:56:9 - | -LL | let v = vec!['a']; - | - has type `Vec<char>` which does not implement `Copy` -LL | yield; - | ^^^^^ yield occurs here, with `v` maybe used later -note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 - | -LL | fn check_copy<T: Copy>(_x: &T) {} - | ^^^^ required by this bound in `check_copy` - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index 8877d45ddda..11b78e3bcf8 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` + = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Sync` is not implemented for `NotSync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:20:9 | @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Send` is not implemented for `NotSend` note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:27:9 | diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr index 4a1e5b078a8..135e8175793 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr @@ -11,7 +11,7 @@ LL | | }; | |_____^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str witness={main::{closure#0}}}` + found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str}` error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 892b5d261c2..3a5e8ec4dab 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -1,14 +1,13 @@ error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:15:30 + --> $DIR/ref-upvar-not-send.rs:15:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _x = x; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: the trait `Sync` is not implemented for `*mut ()` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` @@ -23,16 +22,15 @@ LL | fn assert_send<T: Send>(_: T) {} | ^^^^ required by this bound in `assert_send` error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:23:30 + --> $DIR/ref-upvar-not-send.rs:23:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _y = y; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` diff --git a/tests/ui/impl-trait/issues/issue-55872-2.rs b/tests/ui/impl-trait/issues/issue-55872-2.rs index a3b2225126a..aea00dd9e3d 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.rs +++ b/tests/ui/impl-trait/issues/issue-55872-2.rs @@ -12,7 +12,6 @@ impl<S> Bar for S { type E = impl std::marker::Send; fn foo<T>() -> Self::E { //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-2.stderr b/tests/ui/impl-trait/issues/issue-55872-2.stderr index 51a7dd00ade..91c2ecdc8a4 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-2.stderr @@ -4,13 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | fn foo<T>() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:13:20 - | -LL | fn foo<T>() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-55872-3.rs b/tests/ui/impl-trait/issues/issue-55872-3.rs index 763b4b9fd32..698e7f36234 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.rs +++ b/tests/ui/impl-trait/issues/issue-55872-3.rs @@ -14,7 +14,6 @@ impl<S> Bar for S { fn foo<T>() -> Self::E { //~^ ERROR : Copy` is not satisfied [E0277] //~| ERROR type parameter `T` is part of concrete type - //~| ERROR type parameter `T` is part of concrete type async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr index ce2dd7f02b4..5124c46baeb 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr @@ -1,26 +1,15 @@ -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied - --> $DIR/issue-55872-3.rs:14:20 - | -LL | fn foo<T>() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` -... -LL | async {} - | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` here - error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo<T>() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo<T>() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs index 8c194ec50df..ad7b0674478 100644 --- a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs +++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs @@ -4,6 +4,7 @@ //@ ignore-emscripten no weak symbol support //@ ignore-apple no extern_weak linkage +//@ ignore-aix no extern_weak linkage //@ aux-build:lib.rs diff --git a/tests/ui/loop-match/const-continue-to-block.rs b/tests/ui/loop-match/const-continue-to-block.rs index fd7ebeefeb6..a0f60aaec33 100644 --- a/tests/ui/loop-match/const-continue-to-block.rs +++ b/tests/ui/loop-match/const-continue-to-block.rs @@ -24,3 +24,24 @@ fn const_continue_to_block() -> u8 { } } } + +fn const_continue_to_shadowed_block() -> u8 { + let state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk 1; + } + _ => 'blk: { + //~^ WARN label name `'blk` shadows a label name that is already in scope + #[const_continue] + break 'blk 2; + //~^ ERROR `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + } + } + } + } +} diff --git a/tests/ui/loop-match/const-continue-to-block.stderr b/tests/ui/loop-match/const-continue-to-block.stderr index 3a5339a0394..f4e223bcff1 100644 --- a/tests/ui/loop-match/const-continue-to-block.stderr +++ b/tests/ui/loop-match/const-continue-to-block.stderr @@ -1,8 +1,23 @@ +warning: label name `'blk` shadows a label name that is already in scope + --> $DIR/const-continue-to-block.rs:38:22 + | +LL | state = 'blk: { + | ---- first declared here +... +LL | _ => 'blk: { + | ^^^^ label `'blk` already in scope + error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` --> $DIR/const-continue-to-block.rs:20:27 | LL | break 'b 2; | ^^ -error: aborting due to 1 previous error +error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + --> $DIR/const-continue-to-block.rs:41:27 + | +LL | break 'blk 2; + | ^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/loop-match/invalid.rs b/tests/ui/loop-match/invalid.rs index 0c47b1e0057..08eaf832f56 100644 --- a/tests/ui/loop-match/invalid.rs +++ b/tests/ui/loop-match/invalid.rs @@ -142,6 +142,25 @@ fn break_without_value_unit() { } } +fn break_without_label() { + let mut state = State::A; + let _ = { + #[loop_match] + loop { + state = 'blk: { + match state { + _ => { + #[const_continue] + break State::A; + //~^ ERROR unlabeled `break` inside of a labeled block + //~| ERROR a `#[const_continue]` must break to a label with a value + } + } + } + } + }; +} + fn arm_has_guard(cond: bool) { let mut state = State::A; #[loop_match] diff --git a/tests/ui/loop-match/invalid.stderr b/tests/ui/loop-match/invalid.stderr index 70f246caa9c..9e9796a2ea7 100644 --- a/tests/ui/loop-match/invalid.stderr +++ b/tests/ui/loop-match/invalid.stderr @@ -9,6 +9,12 @@ help: give the `break` a value of the expected type LL | break 'blk /* value */; | +++++++++++ +error[E0695]: unlabeled `break` inside of a labeled block + --> $DIR/invalid.rs:154:25 + | +LL | break State::A; + | ^^^^^^^^^^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label + error: invalid update of the `#[loop_match]` state --> $DIR/invalid.rs:18:9 | @@ -80,14 +86,20 @@ error: a `#[const_continue]` must break to a label with a value LL | break 'blk; | ^^^^^^^^^^ +error: a `#[const_continue]` must break to a label with a value + --> $DIR/invalid.rs:154:25 + | +LL | break State::A; + | ^^^^^^^^^^^^^^ + error: match arms that are part of a `#[loop_match]` cannot have guards - --> $DIR/invalid.rs:155:29 + --> $DIR/invalid.rs:174:29 | LL | State::B if cond => break 'a, | ^^^^ error[E0004]: non-exhaustive patterns: `State::B` and `State::C` not covered - --> $DIR/invalid.rs:168:19 + --> $DIR/invalid.rs:187:19 | LL | match state { | ^^^^^ patterns `State::B` and `State::C` not covered @@ -110,12 +122,12 @@ LL ~ State::B | State::C => todo!(), | error[E0579]: lower range bound must be less than upper - --> $DIR/invalid.rs:185:17 + --> $DIR/invalid.rs:204:17 | LL | 4.0..3.0 => { | ^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0004, E0308, E0579. +Some errors have detailed explanations: E0004, E0308, E0579, E0695. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/macros/builtin-std-paths-fail.stderr b/tests/ui/macros/builtin-std-paths-fail.stderr index 49034c3987b..85d2bd2132f 100644 --- a/tests/ui/macros/builtin-std-paths-fail.stderr +++ b/tests/ui/macros/builtin-std-paths-fail.stderr @@ -104,8 +104,8 @@ LL | #[std::test] | note: found an item that was configured out --> $SRC_DIR/std/src/lib.rs:LL:COL -note: the item is gated here - --> $SRC_DIR/std/src/lib.rs:LL:COL + | + = note: the item is gated here error: aborting due to 16 previous errors diff --git a/tests/ui/macros/macro-inner-attributes.stderr b/tests/ui/macros/macro-inner-attributes.stderr index d74b64db5ac..3c043c38abb 100644 --- a/tests/ui/macros/macro-inner-attributes.stderr +++ b/tests/ui/macros/macro-inner-attributes.stderr @@ -4,6 +4,13 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a` LL | a::bar(); | ^ use of unresolved module or unlinked crate `a` | +note: found an item that was configured out + --> $DIR/macro-inner-attributes.rs:7:7 + | +LL | test!(a, + | ^ +LL | #[cfg(false)], + | ----- the item is gated here help: there is a crate or module with a similar name | LL - a::bar(); diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr index 9215754d4bb..4696bb774e3 100644 --- a/tests/ui/macros/macro-outer-attributes.stderr +++ b/tests/ui/macros/macro-outer-attributes.stderr @@ -7,13 +7,10 @@ LL | a::bar(); note: found an item that was configured out --> $DIR/macro-outer-attributes.rs:9:14 | +LL | #[cfg(false)], + | ----- the item is gated here LL | pub fn bar() { }); | ^^^ -note: the item is gated here - --> $DIR/macro-outer-attributes.rs:8:13 - | -LL | #[cfg(false)], - | ^^^^^ help: consider importing this function | LL + use b::bar; diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index 86f6be85a07..edcffaf6b70 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -93,6 +93,42 @@ LL | struct Priv; LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type +error: type `types::Priv` is more private than the item `types::ES` + --> $DIR/private-in-public-warn.rs:27:9 + | +LL | pub static ES: Priv; + | ^^^^^^^^^^^^^^^^^^^ static `types::ES` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: type `types::Priv` is more private than the item `types::ef1` + --> $DIR/private-in-public-warn.rs:28:9 + | +LL | pub fn ef1(arg: Priv); + | ^^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: type `types::Priv` is more private than the item `types::ef2` + --> $DIR/private-in-public-warn.rs:29:9 + | +LL | pub fn ef2() -> Priv; + | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + error: trait `traits::PrivTr` is more private than the item `traits::Alias` --> $DIR/private-in-public-warn.rs:42:5 | @@ -359,42 +395,6 @@ note: but type `Priv2` is only usable at visibility `pub(self)` LL | struct Priv2; | ^^^^^^^^^^^^ -error: type `types::Priv` is more private than the item `types::ES` - --> $DIR/private-in-public-warn.rs:27:9 - | -LL | pub static ES: Priv; - | ^^^^^^^^^^^^^^^^^^^ static `types::ES` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - -error: type `types::Priv` is more private than the item `types::ef1` - --> $DIR/private-in-public-warn.rs:28:9 - | -LL | pub fn ef1(arg: Priv); - | ^^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - -error: type `types::Priv` is more private than the item `types::ef2` - --> $DIR/private-in-public-warn.rs:29:9 - | -LL | pub fn ef2() -> Priv; - | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - warning: bounds on generic parameters in type aliases are not enforced --> $DIR/private-in-public-warn.rs:42:23 | diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr index 010d77998e3..addb6a075a2 100644 --- a/tests/ui/privacy/projections.stderr +++ b/tests/ui/privacy/projections.stderr @@ -1,16 +1,3 @@ -warning: type `Priv` is more private than the item `Leak` - --> $DIR/projections.rs:3:5 - | -LL | pub type Leak = Priv; - | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` - | -note: but type `Priv` is only usable at visibility `pub(self)` - --> $DIR/projections.rs:2:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - = note: `#[warn(private_interfaces)]` on by default - error[E0446]: private type `Priv` in public interface --> $DIR/projections.rs:24:5 | @@ -29,6 +16,19 @@ LL | struct Priv; LL | type A<T: Trait> = T::A<m::Leak>; | ^^^^^^^^^^^^^^^^ can't leak private type +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + error: type `Priv` is private --> $DIR/projections.rs:14:15 | diff --git a/tests/ui/rustdoc/cfg-rustdoc.rs b/tests/ui/rustdoc/cfg-rustdoc.rs index dd8e1ed97c4..11c48d07552 100644 --- a/tests/ui/rustdoc/cfg-rustdoc.rs +++ b/tests/ui/rustdoc/cfg-rustdoc.rs @@ -1,6 +1,7 @@ -#[cfg(doc)] -pub struct Foo; +#[cfg(doc)] //~ NOTE the item is gated here +pub struct Foo; //~ NOTE found an item that was configured out fn main() { - let f = Foo; //~ ERROR + let f = Foo; //~ ERROR cannot find value `Foo` in this scope + //~^ NOTE not found in this scope } diff --git a/tests/ui/rustdoc/cfg-rustdoc.stderr b/tests/ui/rustdoc/cfg-rustdoc.stderr index 340a8e22482..0e8a5dfea61 100644 --- a/tests/ui/rustdoc/cfg-rustdoc.stderr +++ b/tests/ui/rustdoc/cfg-rustdoc.stderr @@ -3,6 +3,14 @@ error[E0425]: cannot find value `Foo` in this scope | LL | let f = Foo; | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/cfg-rustdoc.rs:2:12 + | +LL | #[cfg(doc)] + | --- the item is gated here +LL | pub struct Foo; + | ^^^ error: aborting due to 1 previous error |
