From 15a71b64b837373b205daaebcf75e179fdfec89e Mon Sep 17 00:00:00 2001 From: Adwin White Date: Tue, 5 Nov 2024 12:41:52 +0800 Subject: [PATCH 1/8] cleanup: Remove outdated comment and logic of `thir_body` --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_mir_build/src/check_unsafety.rs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 41d0b47388cce..30a2e839fb426 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -463,7 +463,7 @@ rustc_queries! { separate_provide_extern } - /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`. + /// Fetch the THIR for a given body. query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { // Perf tests revealed that hashing THIR is inefficient (see #85729). no_hash diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index f3e6301d9d165..33e194fa2462a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1005,10 +1005,6 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { // Runs all other queries that depend on THIR. tcx.ensure_with_value().mir_built(def); let thir = &thir.steal(); - // If `thir` is empty, a type error occurred, skip this body. - if thir.exprs.is_empty() { - return; - } let hir_id = tcx.local_def_id_to_hir_id(def); let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { From 1d6e8476746d79d21bde97243c30937738750227 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 5 Nov 2024 18:23:11 +0000 Subject: [PATCH 2/8] Check for both `StmtKind::MacCall` and `ExprKind::MacCall` --- compiler/rustc_ast/src/ast.rs | 35 +- compiler/rustc_resolve/src/def_collector.rs | 29 +- tests/crashes/131915.rs | 13 - .../const_arg_trivial_macro_expansion-2.rs | 20 + ...const_arg_trivial_macro_expansion-2.stderr | 39 ++ .../const_arg_trivial_macro_expansion.rs | 366 ++++++++++++++++++ 6 files changed, 466 insertions(+), 36 deletions(-) delete mode 100644 tests/crashes/131915.rs create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 997c44cffff03..5f71fb97d768c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1194,7 +1194,7 @@ impl Expr { /// /// Does not ensure that the path resolves to a const param, the caller should check this. pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool { - let this = if strip_identity_block { self.maybe_unwrap_block().1 } else { self }; + let this = if strip_identity_block { self.maybe_unwrap_block() } else { self }; if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() @@ -1206,14 +1206,41 @@ impl Expr { } /// Returns an expression with (when possible) *one* outter brace removed - pub fn maybe_unwrap_block(&self) -> (bool, &Expr) { + pub fn maybe_unwrap_block(&self) -> &Expr { if let ExprKind::Block(block, None) = &self.kind && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind { - (true, expr) + expr } else { - (false, self) + self + } + } + + /// Determines whether this expression is a macro call optionally wrapped in braces . If + /// `already_stripped_block` is set then we do not attempt to peel off a layer of braces. + /// + /// Returns the [`NodeId`] of the macro call and whether a layer of braces has been peeled + /// either before, or part of, this function. + pub fn optionally_braced_mac_call( + &self, + already_stripped_block: bool, + ) -> Option<(bool, NodeId)> { + match &self.kind { + ExprKind::Block(block, None) + if let [stmt] = &*block.stmts + && !already_stripped_block => + { + match &stmt.kind { + StmtKind::MacCall(_) => Some((true, stmt.id)), + StmtKind::Expr(expr) if let ExprKind::MacCall(_) = &expr.kind => { + Some((true, expr.id)) + } + _ => None, + } + } + ExprKind::MacCall(_) => Some((already_stripped_block, self.id)), + _ => None, } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index a825458dc8942..bf27b767a4972 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -130,18 +130,16 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { &self, anon_const: &'a AnonConst, ) -> Option<(PendingAnonConstInfo, NodeId)> { - let (block_was_stripped, expr) = anon_const.value.maybe_unwrap_block(); - match expr { - Expr { kind: ExprKind::MacCall(..), id, .. } => Some(( + anon_const.value.optionally_braced_mac_call(false).map(|(block_was_stripped, id)| { + ( PendingAnonConstInfo { id: anon_const.id, span: anon_const.value.span, block_was_stripped, }, - *id, - )), - _ => None, - } + id, + ) + }) } /// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes @@ -161,18 +159,11 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"), ); - let (block_was_stripped, expr) = if pending_anon.block_was_stripped { - (true, const_arg_sub_expr) - } else { - const_arg_sub_expr.maybe_unwrap_block() - }; - - match expr { - Expr { kind: ExprKind::MacCall(..), id, .. } => { - Some((PendingAnonConstInfo { block_was_stripped, ..pending_anon }, *id)) - } - _ => None, - } + const_arg_sub_expr.optionally_braced_mac_call(pending_anon.block_was_stripped).map( + |(block_was_stripped, id)| { + (PendingAnonConstInfo { block_was_stripped, ..pending_anon }, id) + }, + ) } } diff --git a/tests/crashes/131915.rs b/tests/crashes/131915.rs deleted file mode 100644 index 58d45adcb3be7..0000000000000 --- a/tests/crashes/131915.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #131915 - -macro_rules! y { - ( $($matcher:tt)*) => { - x - }; -} - -const _: A< - { - y! { test.tou8 } - }, ->; diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs new file mode 100644 index 0000000000000..bce7ac5708a59 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs @@ -0,0 +1,20 @@ +// Regression test for #131915 where we did not handle macro calls as +// statements correctly when determining if a const argument should +// have a `DefId` created or not. + +macro_rules! y { + ( $($matcher:tt)*) => { + x + //~^ ERROR: cannot find value `x` in this scope + }; +} + +const _: A< + //~^ ERROR: free constant item without body + //~| ERROR: cannot find type `A` in this scope + { + y! { test.tou8 } + }, +>; + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr new file mode 100644 index 0000000000000..a3211b7762394 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr @@ -0,0 +1,39 @@ +error: free constant item without body + --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:1 + | +LL | / const _: A< +LL | | +LL | | +LL | | { +LL | | y! { test.tou8 } +LL | | }, +LL | | >; + | | ^ help: provide a definition for the constant: `= ;` + | |__| + | + +error[E0412]: cannot find type `A` in this scope + --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:10 + | +LL | const _: A< + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/const_arg_trivial_macro_expansion-2.rs:7:9 + | +LL | x + | ^ not found in this scope +... +LL | y! { test.tou8 } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might be missing a const parameter + | +LL | const _: A< + | +++++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs new file mode 100644 index 0000000000000..2fdd703ab6f32 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs @@ -0,0 +1,366 @@ +//@ known-bug: #132647 +//@ dont-check-compiler-stderr +#![allow(unused_braces)] + +// FIXME(bootstrap): This isn't a known bug, we just don't want to write any error annotations. +// this is hard because macro expansion errors have their span be inside the *definition* of the +// macro rather than the line *invoking* it. This means we would wind up with hundreds of error +// annotations on the macro definitions below rather than on any of the actual lines +// that act as a "test". +// +// It's also made more complicated by the fact that compiletest generates "extra" expected +// notes to give an assertable macro backtrace as otherwise there would *nothing* to annotate +// on the actual test lines. All of these extra notes result in needing to write hundreds of +// unnecessary notes on almost every line in this file. +// +// Even though this is marked `known-bug` it should still fail if this test starts ICEing which +// is "enough" in this case. + +// Test that we correctly create definitions for anon consts even when +// the trivial-ness of the expression is obscured by macro expansions. +// +// Acts as a regression test for: #131915 130321 128016 + +// macros expanding to idents + +macro_rules! unbraced_ident { + () => { + ident + }; +} + +macro_rules! braced_ident { + () => {{ ident }}; +} + +macro_rules! unbraced_unbraced_ident { + () => { + unbraced_ident!() + }; +} + +macro_rules! braced_unbraced_ident { + () => {{ unbraced_ident!() }}; +} + +macro_rules! unbraced_braced_ident { + () => { + braced_ident!() + }; +} + +macro_rules! braced_braced_ident { + () => {{ braced_ident!() }}; +} + +// macros expanding to complex expr + +macro_rules! unbraced_expr { + () => { + ident.other + }; +} + +macro_rules! braced_expr { + () => {{ ident.otherent }}; +} + +macro_rules! unbraced_unbraced_expr { + () => { + unbraced_expr!() + }; +} + +macro_rules! braced_unbraced_expr { + () => {{ unbraced_expr!() }}; +} + +macro_rules! unbraced_braced_expr { + () => { + braced_expr!() + }; +} + +macro_rules! braced_braced_expr { + () => {{ braced_expr!() }}; +} + +#[rustfmt::skip] +mod array_paren_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident!()] { loop {} } + fn array_1() -> [(); braced_unbraced_ident!()] { loop {} } + fn array_2() -> [(); unbraced_braced_ident!()] { loop {} } + fn array_3() -> [(); braced_braced_ident!()] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident!() }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident!() }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident!() }] { loop {} } + fn array_7() -> [(); { braced_braced_ident!() }] { loop {} } + fn array_8() -> [(); unbraced_ident!()] { loop {} } + fn array_9() -> [(); braced_ident!()] { loop {} } + fn array_10() -> [(); { unbraced_ident!() }] { loop {} } + fn array_11() -> [(); { braced_ident!() }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident!()] { loop {} } + fn array_13() -> [(); braced_unbraced_ident!()] { loop {} } + fn array_14() -> [(); unbraced_braced_ident!()] { loop {} } + fn array_15() -> [(); braced_braced_ident!()] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident!() }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident!() }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident!() }] { loop {} } + fn array_19() -> [(); { braced_braced_ident!() }] { loop {} } + fn array_20() -> [(); unbraced_ident!()] { loop {} } + fn array_21() -> [(); braced_ident!()] { loop {} } + fn array_22() -> [(); { unbraced_ident!() }] { loop {} } + fn array_23() -> [(); { braced_ident!() }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr!()] { loop {} } + fn array_25() -> [(); braced_unbraced_expr!()] { loop {} } + fn array_26() -> [(); unbraced_braced_expr!()] { loop {} } + fn array_27() -> [(); braced_braced_expr!()] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr!() }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr!() }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr!() }] { loop {} } + fn array_31() -> [(); { braced_braced_expr!() }] { loop {} } + fn array_32() -> [(); unbraced_expr!()] { loop {} } + fn array_33() -> [(); braced_expr!()] { loop {} } + fn array_34() -> [(); { unbraced_expr!() }] { loop {} } + fn array_35() -> [(); { braced_expr!() }] { loop {} } +} + +#[rustfmt::skip] +mod array_brace_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident!{}] { loop {} } + fn array_1() -> [(); braced_unbraced_ident!{}] { loop {} } + fn array_2() -> [(); unbraced_braced_ident!{}] { loop {} } + fn array_3() -> [(); braced_braced_ident!{}] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident!{} }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident!{} }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident!{} }] { loop {} } + fn array_7() -> [(); { braced_braced_ident!{} }] { loop {} } + fn array_8() -> [(); unbraced_ident!{}] { loop {} } + fn array_9() -> [(); braced_ident!{}] { loop {} } + fn array_10() -> [(); { unbraced_ident!{} }] { loop {} } + fn array_11() -> [(); { braced_ident!{} }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident!{}] { loop {} } + fn array_13() -> [(); braced_unbraced_ident!{}] { loop {} } + fn array_14() -> [(); unbraced_braced_ident!{}] { loop {} } + fn array_15() -> [(); braced_braced_ident!{}] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident!{} }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident!{} }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident!{} }] { loop {} } + fn array_19() -> [(); { braced_braced_ident!{} }] { loop {} } + fn array_20() -> [(); unbraced_ident!{}] { loop {} } + fn array_21() -> [(); braced_ident!{}] { loop {} } + fn array_22() -> [(); { unbraced_ident!{} }] { loop {} } + fn array_23() -> [(); { braced_ident!{} }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr!{}] { loop {} } + fn array_25() -> [(); braced_unbraced_expr!{}] { loop {} } + fn array_26() -> [(); unbraced_braced_expr!{}] { loop {} } + fn array_27() -> [(); braced_braced_expr!{}] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr!{} }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr!{} }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr!{} }] { loop {} } + fn array_31() -> [(); { braced_braced_expr!{} }] { loop {} } + fn array_32() -> [(); unbraced_expr!{}] { loop {} } + fn array_33() -> [(); braced_expr!{}] { loop {} } + fn array_34() -> [(); { unbraced_expr!{} }] { loop {} } + fn array_35() -> [(); { braced_expr!{} }] { loop {} } +} + +#[rustfmt::skip] +mod array_square_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident![]] { loop {} } + fn array_1() -> [(); braced_unbraced_ident![]] { loop {} } + fn array_2() -> [(); unbraced_braced_ident![]] { loop {} } + fn array_3() -> [(); braced_braced_ident![]] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident![] }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident![] }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident![] }] { loop {} } + fn array_7() -> [(); { braced_braced_ident![] }] { loop {} } + fn array_8() -> [(); unbraced_ident![]] { loop {} } + fn array_9() -> [(); braced_ident![]] { loop {} } + fn array_10() -> [(); { unbraced_ident![] }] { loop {} } + fn array_11() -> [(); { braced_ident![] }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident![]] { loop {} } + fn array_13() -> [(); braced_unbraced_ident![]] { loop {} } + fn array_14() -> [(); unbraced_braced_ident![]] { loop {} } + fn array_15() -> [(); braced_braced_ident![]] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident![] }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident![] }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident![] }] { loop {} } + fn array_19() -> [(); { braced_braced_ident![] }] { loop {} } + fn array_20() -> [(); unbraced_ident![]] { loop {} } + fn array_21() -> [(); braced_ident![]] { loop {} } + fn array_22() -> [(); { unbraced_ident![] }] { loop {} } + fn array_23() -> [(); { braced_ident![] }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr![]] { loop {} } + fn array_25() -> [(); braced_unbraced_expr![]] { loop {} } + fn array_26() -> [(); unbraced_braced_expr![]] { loop {} } + fn array_27() -> [(); braced_braced_expr![]] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr![] }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr![] }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr![] }] { loop {} } + fn array_31() -> [(); { braced_braced_expr![] }] { loop {} } + fn array_32() -> [(); unbraced_expr![]] { loop {} } + fn array_33() -> [(); braced_expr![]] { loop {} } + fn array_34() -> [(); { unbraced_expr![] }] { loop {} } + fn array_35() -> [(); { braced_expr![] }] { loop {} } +} + +struct Foo; + +#[rustfmt::skip] +mod adt_paren_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident!() }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident!() }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident!() }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident!() }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident!() }> { loop {} } + fn adt_11() -> Foo<{ braced_ident!() }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident!() }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident!() }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident!() }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident!() }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident!() }> { loop {} } + fn adt_23() -> Foo<{ braced_ident!() }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr!() }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr!() }> { loop {} } + fn array_35() -> Foo<{ braced_expr!() }> { loop {} } +} + +#[rustfmt::skip] +mod adt_brace_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident!{} }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident!{} }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident!{} }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident!{} }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident!{} }> { loop {} } + fn adt_11() -> Foo<{ braced_ident!{} }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident!{} }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident!{} }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident!{} }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident!{} }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident!{} }> { loop {} } + fn adt_23() -> Foo<{ braced_ident!{} }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr!{} }> { loop {} } + fn array_35() -> Foo<{ braced_expr!{} }> { loop {} } +} + +#[rustfmt::skip] +mod adt_square_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident![] }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident![] }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident![] }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident![] }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident![] }> { loop {} } + fn adt_11() -> Foo<{ braced_ident![] }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident![] }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident![] }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident![] }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident![] }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident![] }> { loop {} } + fn adt_23() -> Foo<{ braced_ident![] }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr![] }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr![] }> { loop {} } + fn array_35() -> Foo<{ braced_expr![] }> { loop {} } +} + +fn main() {} From 544b9f9a94384742f9e1649e9318419d88785e19 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 8 Nov 2024 15:34:15 -0800 Subject: [PATCH 3/8] Update mdbook to 0.4.42 --- src/doc/rust-by-example | 2 +- src/tools/rustbook/.gitignore | 1 + src/tools/rustbook/Cargo.lock | 24 ++++++++++++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 src/tools/rustbook/.gitignore diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 9db78608b17d5..e1d1f2cdcee4d 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 9db78608b17d5f4a6c033b8a3038466b87d63206 +Subproject commit e1d1f2cdcee4d52b9a01ff7c448be4372a377b70 diff --git a/src/tools/rustbook/.gitignore b/src/tools/rustbook/.gitignore new file mode 100644 index 0000000000000..ea8c4bf7f35f6 --- /dev/null +++ b/src/tools/rustbook/.gitignore @@ -0,0 +1 @@ +/target diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 27ccb205b50ab..914b03c8679b1 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -441,11 +441,12 @@ dependencies = [ [[package]] name = "handlebars" -version = "5.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315" dependencies = [ "log", + "num-order", "pest", "pest_derive", "serde", @@ -645,9 +646,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" +checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3" dependencies = [ "ammonia", "anyhow", @@ -762,6 +763,21 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + [[package]] name = "num-traits" version = "0.2.19" From b2d1874dc20824d10d2e96b9066e23e3a977f854 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 Nov 2024 13:03:25 +0100 Subject: [PATCH 4/8] elem_offset / subslice_range: use addr() instead of 'as usize' --- library/core/src/slice/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 52d2179b04de1..ce9d04d01d7ed 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4578,8 +4578,8 @@ impl [T] { panic!("elements are zero-sized"); } - let self_start = self.as_ptr() as usize; - let elem_start = element as *const T as usize; + let self_start = self.as_ptr().addr(); + let elem_start = ptr::from_ref(element).addr(); let byte_offset = elem_start.wrapping_sub(self_start); @@ -4631,8 +4631,8 @@ impl [T] { panic!("elements are zero-sized"); } - let self_start = self.as_ptr() as usize; - let subslice_start = subslice.as_ptr() as usize; + let self_start = self.as_ptr().addr(); + let subslice_start = subslice.as_ptr().addr(); let byte_start = subslice_start.wrapping_sub(self_start); From ae3c68db344f26d79c0a133a1a46c7929b1ea9ad Mon Sep 17 00:00:00 2001 From: binarycat Date: Sun, 10 Nov 2024 13:22:58 -0600 Subject: [PATCH 5/8] split up the first paragraph of doc comments for better summaries --- library/alloc/src/rc.rs | 4 +++- library/alloc/src/sync.rs | 4 +++- library/alloc/src/task.rs | 8 +++++--- library/std/src/sync/mpmc/mod.rs | 2 ++ library/std/src/sync/mpsc/mod.rs | 2 ++ 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 64b0520e9834d..e8941bbd41da0 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2931,7 +2931,9 @@ impl> ToRcSlice for I { } /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the -/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// managed allocation. +/// +/// The allocation is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [Option]<[Rc]\>. /// /// Since a `Weak` reference does not count towards ownership, it will not diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f348fba62204f..bba4f1220e4f4 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -290,7 +290,9 @@ impl Arc { } /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the -/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// managed allocation. +/// +/// The allocation is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [Option]<[Arc]\>. /// /// Since a `Weak` reference does not count towards ownership, it will not diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 27589aed2f97c..0f8e74300a491 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -176,9 +176,11 @@ fn raw_waker(waker: Arc) -> RawWaker { ) } -/// An analogous trait to `Wake` but used to construct a `LocalWaker`. This API -/// works in exactly the same way as `Wake`, except that it uses an `Rc` instead -/// of an `Arc`, and the result is a `LocalWaker` instead of a `Waker`. +/// An analogous trait to `Wake` but used to construct a `LocalWaker`. +/// +/// This API works in exactly the same way as `Wake`, +/// except that it uses an `Rc` instead of an `Arc`, +/// and the result is a `LocalWaker` instead of a `Waker`. /// /// The benefits of using `LocalWaker` over `Waker` are that it allows the local waker /// to hold data that does not implement `Send` and `Sync`. Additionally, it saves calls diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 44e146a89bafb..0cf4902d6d59b 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -153,6 +153,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::time::{Duration, Instant}; /// Creates a new asynchronous channel, returning the sender/receiver halves. +/// /// All data sent on the [`Sender`] will become available on the [`Receiver`] in /// the same order as it was sent, and no [`send`] will block the calling thread /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will @@ -201,6 +202,7 @@ pub fn channel() -> (Sender, Receiver) { } /// Creates a new synchronous, bounded channel. +/// /// All data sent on the [`Sender`] will become available on the [`Receiver`] /// in the same order as it was sent. Like asynchronous [`channel`]s, the /// [`Receiver`] will block until a message becomes available. `sync_channel` diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index 83a93a0636956..c86b546e01169 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -483,6 +483,7 @@ pub enum TrySendError { } /// Creates a new asynchronous channel, returning the sender/receiver halves. +/// /// All data sent on the [`Sender`] will become available on the [`Receiver`] in /// the same order as it was sent, and no [`send`] will block the calling thread /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will @@ -527,6 +528,7 @@ pub fn channel() -> (Sender, Receiver) { } /// Creates a new synchronous, bounded channel. +/// /// All data sent on the [`SyncSender`] will become available on the [`Receiver`] /// in the same order as it was sent. Like asynchronous [`channel`]s, the /// [`Receiver`] will block until a message becomes available. `sync_channel` From 02add7d0fbc65296af285fe5c62b36b42a9f476f Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 1 Nov 2024 19:47:07 -0700 Subject: [PATCH 6/8] Provide placeholder generic arguments for traits in "no method found for type parameter" suggestions --- compiler/rustc_hir_typeck/src/lib.rs | 1 + .../rustc_hir_typeck/src/method/suggest.rs | 64 +++++++++++++------ .../no-method-found-suggest-trait-args.rs | 30 +++++++++ .../no-method-found-suggest-trait-args.stderr | 63 ++++++++++++++++++ 4 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 tests/ui/suggestions/no-method-found-suggest-trait-args.rs create mode 100644 tests/ui/suggestions/no-method-found-suggest-trait-args.stderr diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index f5987a11fa56d..63dccf8b0ce04 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -4,6 +4,7 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cb20a1d7c7b69..8772599e31614 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3874,22 +3874,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param.name.ident(), )); let bounds_span = hir_generics.bounds_span_for_suggestions(def_id); + let mut applicability = Applicability::MaybeIncorrect; + // Format the path of each suggested candidate, providing placeholders + // for any generic arguments without defaults. + let candidate_strs: Vec<_> = candidates + .iter() + .map(|cand| { + let cand_path = self.tcx.def_path_str(cand.def_id); + let cand_params = &self.tcx.generics_of(cand.def_id).own_params; + let cand_args: String = cand_params + .iter() + .skip(1) + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Type { + has_default: true, + .. + } + | ty::GenericParamDefKind::Const { + has_default: true, + .. + } => None, + _ => Some(param.name.as_str()), + }) + .intersperse(", ") + .collect(); + if cand_args.is_empty() { + cand_path + } else { + applicability = Applicability::HasPlaceholders; + format!("{cand_path}") + } + }) + .collect(); + if rcvr_ty.is_ref() && param.is_impl_trait() && let Some((bounds_span, _)) = bounds_span { err.multipart_suggestions( msg, - candidates.iter().map(|t| { + candidate_strs.iter().map(|cand| { vec![ (param.span.shrink_to_lo(), "(".to_string()), - ( - bounds_span, - format!(" + {})", self.tcx.def_path_str(t.def_id)), - ), + (bounds_span, format!(" + {cand})")), ] }), - Applicability::MaybeIncorrect, + applicability, ); return; } @@ -3905,16 +3935,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (param.span.shrink_to_hi(), Introducer::Colon, None) }; - let all_suggs = candidates.iter().map(|cand| { - let suggestion = format!( - "{} {}", - match introducer { - Introducer::Plus => " +", - Introducer::Colon => ":", - Introducer::Nothing => "", - }, - self.tcx.def_path_str(cand.def_id) - ); + let all_suggs = candidate_strs.iter().map(|cand| { + let suggestion = format!("{} {cand}", match introducer { + Introducer::Plus => " +", + Introducer::Colon => ":", + Introducer::Nothing => "", + },); let mut suggs = vec![]; @@ -3928,11 +3954,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggs }); - err.multipart_suggestions( - msg, - all_suggs, - Applicability::MaybeIncorrect, - ); + err.multipart_suggestions(msg, all_suggs, applicability); return; } diff --git a/tests/ui/suggestions/no-method-found-suggest-trait-args.rs b/tests/ui/suggestions/no-method-found-suggest-trait-args.rs new file mode 100644 index 0000000000000..d51f86b29e81d --- /dev/null +++ b/tests/ui/suggestions/no-method-found-suggest-trait-args.rs @@ -0,0 +1,30 @@ +/// Tests that suggestions to add trait bounds that would enable using a method include appropriate +/// placeholder arguments for that trait. + +trait Trait { + fn method(&self) {} +} + +trait Trait2<'a, A, const B: u8, C = (), const D: u8 = 0> { + fn method2(&self) {} +} + +fn foo(value: T) { + //~^ SUGGESTION : Trait + //~| SUGGESTION : Trait2 + value.method(); + //~^ ERROR no method named `method` found for type parameter `T` in the current scope [E0599] + value.method2(); + //~^ ERROR no method named `method2` found for type parameter `T` in the current scope [E0599] +} + +fn bar(value: impl Copy) { + //~^ SUGGESTION + Trait + //~| SUGGESTION + Trait2 + value.method(); + //~^ ERROR no method named `method` found for type parameter `impl Copy` in the current scope [E0599] + value.method2(); + //~^ ERROR no method named `method2` found for type parameter `impl Copy` in the current scope [E0599] +} + +fn main() {} diff --git a/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr b/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr new file mode 100644 index 0000000000000..3dcd4667fa099 --- /dev/null +++ b/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr @@ -0,0 +1,63 @@ +error[E0599]: no method named `method` found for type parameter `T` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:15:11 + | +LL | fn foo(value: T) { + | - method `method` not found for this type parameter +... +LL | value.method(); + | ^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo>(value: T) { + | ++++++++++++++++ + +error[E0599]: no method named `method2` found for type parameter `T` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:17:11 + | +LL | fn foo(value: T) { + | - method `method2` not found for this type parameter +... +LL | value.method2(); + | ^^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method2`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo>(value: T) { + | ++++++++++++++++++++++++ + +error[E0599]: no method named `method` found for type parameter `impl Copy` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:24:11 + | +LL | fn bar(value: impl Copy) { + | --------- method `method` not found for this type parameter +... +LL | value.method(); + | ^^^^^^ method not found in `impl Copy` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Copy` with it: + | +LL | fn bar(value: impl Copy + Trait) { + | ++++++++++++++++ + +error[E0599]: no method named `method2` found for type parameter `impl Copy` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:26:11 + | +LL | fn bar(value: impl Copy) { + | --------- method `method2` not found for this type parameter +... +LL | value.method2(); + | ^^^^^^^ method not found in `impl Copy` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method2`, perhaps you need to restrict type parameter `impl Copy` with it: + | +LL | fn bar(value: impl Copy + Trait2) { + | ++++++++++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. From 2ddb91acd1867bbaad3986fdef63d4953a0fb37a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Nov 2024 16:30:37 -0800 Subject: [PATCH 7/8] Check for null in the `alloc_zeroed` example We should demonstrate good behavior, just like #99198 did for `alloc`. --- library/alloc/src/alloc.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index a91659b6de5ad..98402a4620158 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -155,11 +155,14 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// # Examples /// /// ``` -/// use std::alloc::{alloc_zeroed, dealloc, Layout}; +/// use std::alloc::{alloc_zeroed, dealloc, handle_alloc_error, Layout}; /// /// unsafe { /// let layout = Layout::new::(); /// let ptr = alloc_zeroed(layout); +/// if ptr.is_null() { +/// handle_alloc_error(layout); +/// } /// /// assert_eq!(*(ptr as *mut u16), 0); /// From 8473e3f6af8eaad2686bf492241b8f5766034d3e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 12 Nov 2024 01:48:04 +0000 Subject: [PATCH 8/8] Make sure that we suggest turbofishing the right type arg --- compiler/rustc_hir_typeck/src/fallback.rs | 6 ++- .../never-type-fallback-breaking.e2021.fixed | 52 +++++++++++++++++++ .../never-type-fallback-breaking.e2021.stderr | 29 +++++++++-- .../never-type-fallback-breaking.e2024.stderr | 31 +++++++++-- .../editions/never-type-fallback-breaking.rs | 14 +++++ 5 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 tests/ui/editions/never-type-fallback-breaking.e2021.fixed diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 97f3807c2521e..7719facccc7ba 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -621,7 +621,11 @@ impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> { .iter() .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) .count(); - for (idx, arg) in args.iter().enumerate() { + for (idx, arg) in args + .iter() + .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) + .enumerate() + { if let Some(ty) = arg.as_type() && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed new file mode 100644 index 0000000000000..3fed16f0ee719 --- /dev/null +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -0,0 +1,52 @@ +//@ revisions: e2021 e2024 +// +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +// +//@[e2021] run-pass +//@[e2021] run-rustfix +//@[e2024] check-fail + +fn main() { + m(); + q(); + let _ = meow(); +} + +fn m() { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + let x: () = match true { + true => Default::default(), + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + false => panic!("..."), + }; + + dbg!(x); +} + +fn q() -> Option<()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + fn deserialize() -> Option { + Some(T::default()) + } + + deserialize::<()>()?; + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + + None +} + +// Make sure we turbofish the right argument +fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + Err(()) +} +fn meow() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + help::<(), _>(1)?; + //[e2024]~^ error: the trait bound `(): From` is not satisfied + Ok(()) +} diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 79eee2a3defd0..fdc97e54d4e44 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -1,5 +1,5 @@ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:15:1 + --> $DIR/never-type-fallback-breaking.rs:17:1 | LL | fn m() { | ^^^^^^ @@ -8,7 +8,7 @@ LL | fn m() { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:19:17 + --> $DIR/never-type-fallback-breaking.rs:21:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let x: () = match true { | ++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:27:1 + --> $DIR/never-type-fallback-breaking.rs:29:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | fn q() -> Option<()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:34:5 + --> $DIR/never-type-fallback-breaking.rs:36:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -37,5 +37,24 @@ help: use `()` annotations to avoid fallback changes LL | deserialize::<()>()?; | ++++++ -warning: 2 warnings emitted +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:46:1 + | +LL | fn meow() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `(): From` will fail + --> $DIR/never-type-fallback-breaking.rs:49:5 + | +LL | help(1)?; + | ^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | help::<(), _>(1)?; + | +++++++++ + +warning: 3 warnings emitted diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 461e4ae0bdf6d..6258247f8b28e 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:19:17 + --> $DIR/never-type-fallback-breaking.rs:21:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ LL | true => Default::default(), = help: did you intend to use the type `()` here instead? error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:34:5 + --> $DIR/never-type-fallback-breaking.rs:36:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,11 +16,34 @@ LL | deserialize()?; = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:30:23 + --> $DIR/never-type-fallback-breaking.rs:32:23 | LL | fn deserialize() -> Option { | ^^^^^^^ required by this bound in `deserialize` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `(): From` is not satisfied + --> $DIR/never-type-fallback-breaking.rs:49:5 + | +LL | help(1)?; + | ^^^^^^^ the trait `From` is not implemented for `()` + | + = help: the following other types implement trait `From`: + `(T, T)` implements `From<[T; 2]>` + `(T, T, T)` implements `From<[T; 3]>` + `(T, T, T, T)` implements `From<[T; 4]>` + `(T, T, T, T, T)` implements `From<[T; 5]>` + `(T, T, T, T, T, T)` implements `From<[T; 6]>` + `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` + `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` + `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` + and 4 others + = note: required for `!` to implement `Into<()>` +note: required by a bound in `help` + --> $DIR/never-type-fallback-breaking.rs:43:20 + | +LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + | ^^^^^^^^ required by this bound in `help` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 7b4a1b1de0487..71d36f3a2d92b 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -5,11 +5,13 @@ //@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass +//@[e2021] run-rustfix //@[e2024] check-fail fn main() { m(); q(); + let _ = meow(); } fn m() { @@ -36,3 +38,15 @@ fn q() -> Option<()> { None } + +// Make sure we turbofish the right argument +fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + Err(()) +} +fn meow() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + help(1)?; + //[e2024]~^ error: the trait bound `(): From` is not satisfied + Ok(()) +}