From 745c600617bc5dd1405cb53b1f79e5f421d62b0f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 10:13:12 +0000 Subject: [PATCH 01/12] Talk about `gen fn` in diagnostics about `gen fn` --- compiler/rustc_parse/messages.ftl | 4 ++-- compiler/rustc_parse/src/errors.rs | 4 ++-- compiler/rustc_parse/src/parser/item.rs | 2 +- tests/ui/coroutine/gen_fn.e2024.stderr | 4 ++-- tests/ui/coroutine/gen_fn.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 9bedd7b8a338a..9ba1f0a5df914 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -278,8 +278,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}` parse_function_body_equals_expr = function body cannot be `= expression;` .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` -parse_gen_block = `gen` blocks are not yet implemented - .help = only the keyword is reserved for now +parse_gen_fn = `gen` functions are not yet implemented + .help = for now you can use `gen {"{}"}` blocks and return `impl Iterator` instead parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index c0e94d15da0bf..e5cd91a32a7bf 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -521,9 +521,9 @@ pub(crate) struct CatchAfterTry { } #[derive(Diagnostic)] -#[diag(parse_gen_block)] +#[diag(parse_gen_fn)] #[help] -pub(crate) struct GenBlock { +pub(crate) struct GenFn { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index a9f456d64cd11..55ad3f42938b4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2372,7 +2372,7 @@ impl<'a> Parser<'a> { } if let Gen::Yes { span, .. } = genness { - self.sess.emit_err(errors::GenBlock { span }); + self.sess.emit_err(errors::GenFn { span }); } if !self.eat_keyword_case(kw::Fn, case) { diff --git a/tests/ui/coroutine/gen_fn.e2024.stderr b/tests/ui/coroutine/gen_fn.e2024.stderr index 41bd04d976912..388e10fd65e44 100644 --- a/tests/ui/coroutine/gen_fn.e2024.stderr +++ b/tests/ui/coroutine/gen_fn.e2024.stderr @@ -1,10 +1,10 @@ -error: `gen` blocks are not yet implemented +error: `gen` functions are not yet implemented --> $DIR/gen_fn.rs:4:1 | LL | gen fn foo() {} | ^^^ | - = help: only the keyword is reserved for now + = help: for now you can use `gen {}` blocks and return `impl Iterator` instead error: aborting due to previous error diff --git a/tests/ui/coroutine/gen_fn.rs b/tests/ui/coroutine/gen_fn.rs index 9566660dfb566..da515f263b00a 100644 --- a/tests/ui/coroutine/gen_fn.rs +++ b/tests/ui/coroutine/gen_fn.rs @@ -3,6 +3,6 @@ gen fn foo() {} //[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` -//[e2024]~^^ ERROR: `gen` blocks are not yet implemented +//[e2024]~^^ ERROR: `gen` functions are not yet implemented fn main() {} From bc926f7c33c5fa12a5d42c1c597245d047346fd6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 10:23:57 +0000 Subject: [PATCH 02/12] Add a custom panic message for resuming `gen` blocks after they panicked --- compiler/rustc_middle/messages.ftl | 2 ++ compiler/rustc_middle/src/mir/terminator.rs | 3 +-- tests/ui/coroutine/gen_block_panic.rs | 25 +++++++++++++++++++++ tests/ui/coroutine/gen_block_panic.stderr | 12 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/ui/coroutine/gen_block_panic.rs create mode 100644 tests/ui/coroutine/gen_block_panic.stderr diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 37ff5bcf1e2da..27d555d7e26c7 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -12,6 +12,8 @@ middle_assert_coroutine_resume_after_return = coroutine resumed after completion middle_assert_divide_by_zero = attempt to divide `{$val}` by zero +middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked + middle_assert_misaligned_ptr_deref = misaligned pointer dereference: address must be a multiple of {$required} but is {$found} diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index c2aa015f4b7e7..9dfbe1733cc51 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -250,8 +250,7 @@ impl AssertKind { middle_assert_coroutine_resume_after_return } ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic, - // FIXME(gen_blocks): custom error message for `gen` blocks - ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_async_resume_after_panic, + ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic, ResumedAfterPanic(CoroutineKind::Coroutine) => { middle_assert_coroutine_resume_after_panic } diff --git a/tests/ui/coroutine/gen_block_panic.rs b/tests/ui/coroutine/gen_block_panic.rs new file mode 100644 index 0000000000000..33e2b4b265a11 --- /dev/null +++ b/tests/ui/coroutine/gen_block_panic.rs @@ -0,0 +1,25 @@ +//compile-flags: --edition 2024 -Zunstable-options +// run-pass +#![feature(gen_blocks)] + +fn main() { + let mut iter = gen { + yield 42; + panic!("foo"); + yield 69; //~ WARN: unreachable statement + }; + assert_eq!(iter.next(), Some(42)); + let mut tmp = std::panic::AssertUnwindSafe(&mut iter); + match std::panic::catch_unwind(move || tmp.next()) { + Ok(_) => unreachable!(), + Err(err) => assert_eq!(*err.downcast::<&'static str>().unwrap(), "foo"), + } + + match std::panic::catch_unwind(move || iter.next()) { + Ok(_) => unreachable!(), + Err(err) => assert_eq!( + *err.downcast::<&'static str>().unwrap(), + "`gen fn` should just keep returning `None` after panicking", + ), + } +} diff --git a/tests/ui/coroutine/gen_block_panic.stderr b/tests/ui/coroutine/gen_block_panic.stderr new file mode 100644 index 0000000000000..33d2a95cab8bc --- /dev/null +++ b/tests/ui/coroutine/gen_block_panic.stderr @@ -0,0 +1,12 @@ +warning: unreachable statement + --> $DIR/gen_block_panic.rs:9:9 + | +LL | panic!("foo"); + | ------------- any code following this expression is unreachable +LL | yield 69; + | ^^^^^^^^^ unreachable statement + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 1 warning emitted + From 972ee01b69378280b4911caaae0bd95ea8d790c3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 13:38:54 +0000 Subject: [PATCH 03/12] Add regression test --- .../nested_impl_trait_in_assoc_ty.rs | 37 +++++++++++++++++++ .../nested_impl_trait_in_assoc_ty.stderr | 15 ++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs create mode 100644 tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr diff --git a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs new file mode 100644 index 0000000000000..859a6807c2caa --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs @@ -0,0 +1,37 @@ +// edition: 2021 + +#![feature(impl_trait_in_assoc_type)] + +use std::future::Future; + +pub struct MemtableLocalStateStore { + mem_table: MemTable, +} + +impl LocalStateStore for MemtableLocalStateStore { + type IterStream<'a> = impl Sized + 'a where Self: 'a; + + fn iter(&self) -> impl Future> + '_ { + async move { merge_stream(self.mem_table.iter()) } + } +} + +trait LocalStateStore { + type IterStream<'a> + where + Self: 'a; + + fn iter(&self) -> impl Future> + '_; +} + +struct MemTable; + +impl MemTable { + fn iter<'a>(&'a self) -> impl Iterator { + std::iter::empty() + } +} + +pub(crate) async fn merge_stream<'a>(mem_table_iter: impl Iterator) {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr new file mode 100644 index 0000000000000..30b3deca1e420 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr @@ -0,0 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/nested_impl_trait_in_assoc_ty.rs:15:9 + | +LL | async move { merge_stream(self.mem_table.iter()) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `'_` is not a generic parameter + | +note: for this opaque type + --> $DIR/nested_impl_trait_in_assoc_ty.rs:35:1 + | +LL | pub(crate) async fn merge_stream<'a>(mem_table_iter: impl Iterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. From 8d03e1394f90c43c25c00bcb6ba2dd621215cac4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 13:46:44 +0000 Subject: [PATCH 04/12] Don't treat closures/coroutines as part of the public API --- compiler/rustc_ty_utils/src/opaque_types.rs | 1 + compiler/rustc_ty_utils/src/sig_types.rs | 29 +++++-------------- .../nested_impl_trait_in_assoc_ty.rs | 7 +++++ .../nested_impl_trait_in_assoc_ty.stderr | 15 ---------- 4 files changed, 16 insertions(+), 36 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index f7d54566cb704..9242a1a751bc7 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -121,6 +121,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { } impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> { + #[instrument(skip(self), ret, level = "trace")] fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow { self.visit_spanned(span, value); ControlFlow::Continue(()) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 1ab39974e0f2a..5d4aee318c61f 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use rustc_hir::{def::DefKind, def_id::LocalDefId}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; @@ -25,24 +25,9 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( let kind = tcx.def_kind(item); trace!(?kind); match kind { - DefKind::Coroutine => { - match tcx.type_of(item).instantiate_identity().kind() { - ty::Coroutine(_, args, _) => visitor.visit(tcx.def_span(item), args.as_coroutine().sig())?, - _ => bug!(), - } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; - } - } - // Walk over the signature of the function-like - DefKind::Closure | DefKind::AssocFn | DefKind::Fn => { - let ty_sig = match kind { - DefKind::Closure => match tcx.type_of(item).instantiate_identity().kind() { - ty::Closure(_, args) => args.as_closure().sig(), - _ => bug!(), - }, - _ => tcx.fn_sig(item).instantiate_identity(), - }; + // Walk over the signature of the function + DefKind::AssocFn | DefKind::Fn => { + let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir().get_by_def_id(item).fn_decl().unwrap(); // Walk over the inputs and outputs manually in order to get good spans for them. visitor.visit(hir_sig.output.span(), ty_sig.output()); @@ -79,8 +64,10 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( visitor.visit(span, pred)?; } } - // Does not have a syntactical signature - DefKind::InlineConst => {} + // These are not part of a public API, they can only appear as hidden types, and there + // the interesting parts are solely in the signature of the containing item's opaque type + // or dyn type. + DefKind::InlineConst | DefKind::Closure | DefKind::Coroutine => {} DefKind::Impl { of_trait } => { if of_trait { let span = tcx.hir().get_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; diff --git a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs index 859a6807c2caa..5f3dbaa179891 100644 --- a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs +++ b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs @@ -1,4 +1,11 @@ +//! This test checks that we do not walk types in async blocks for +//! determining the opaque types that appear in a signature. async blocks, +//! all other coroutines and closures are always private and not part of +//! a signature. They become part of a signature via `dyn Trait` or `impl Trait`, +//! which is something that we process abstractly without looking at its hidden +//! types. // edition: 2021 +// check-pass #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr deleted file mode 100644 index 30b3deca1e420..0000000000000 --- a/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0792]: non-defining opaque type use in defining scope - --> $DIR/nested_impl_trait_in_assoc_ty.rs:15:9 - | -LL | async move { merge_stream(self.mem_table.iter()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `'_` is not a generic parameter - | -note: for this opaque type - --> $DIR/nested_impl_trait_in_assoc_ty.rs:35:1 - | -LL | pub(crate) async fn merge_stream<'a>(mem_table_iter: impl Iterator) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0792`. From 251021c1ab095e6448cfe060e1d43a4bab2711f5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 13:47:08 +0000 Subject: [PATCH 05/12] Merge two equal match arms --- compiler/rustc_ty_utils/src/sig_types.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 5d4aee318c61f..741ee8f0b0017 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -82,12 +82,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; }} - DefKind::Trait => { - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; - } - } - DefKind::TraitAlias => { + DefKind::TraitAlias | DefKind::Trait => { for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } From 43ff2a7e5095a9d79a3c4acde1208df6aa7bf296 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 13:48:34 +0000 Subject: [PATCH 06/12] Some manual rustfmt as rustfmt is broken on this file --- compiler/rustc_ty_utils/src/sig_types.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 741ee8f0b0017..ccdc6120196ac 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -46,7 +46,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( Some(ty) => ty.span, _ => tcx.def_span(item), }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + visitor.visit(span, tcx.type_of(item).instantiate_identity()); for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -59,7 +59,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + visitor.visit(span, tcx.type_of(item).instantiate_identity()); for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -81,7 +81,8 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( visitor.visit(span, tcx.type_of(item).instantiate_identity()); for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; - }} + } + } DefKind::TraitAlias | DefKind::Trait => { for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; From d5e836cf0ce49761524e9c8ffb121e186e774052 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 30 Oct 2023 15:31:00 +0100 Subject: [PATCH 07/12] Correctly handle nested or-patterns in column-wise analyses --- compiler/rustc_mir_build/src/thir/pattern/usefulness.rs | 2 +- tests/ui/or-patterns/exhaustiveness-pass.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 25e0f3ceaa473..59f0849d08b3d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -931,7 +931,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { let specialized = pat.specialize(pcx, &ctor); for (subpat, column) in specialized.iter().zip(&mut specialized_columns) { if subpat.is_or_pat() { - column.patterns.extend(subpat.iter_fields()) + column.patterns.extend(subpat.flatten_or_pat()) } else { column.patterns.push(subpat) } diff --git a/tests/ui/or-patterns/exhaustiveness-pass.rs b/tests/ui/or-patterns/exhaustiveness-pass.rs index e8c8a0e7ba52a..428b9a19fe69b 100644 --- a/tests/ui/or-patterns/exhaustiveness-pass.rs +++ b/tests/ui/or-patterns/exhaustiveness-pass.rs @@ -35,4 +35,10 @@ fn main() { ((0, 0) | (1, 0),) => {} _ => {} } + + // This one caused ICE https://github.com/rust-lang/rust/issues/117378 + match (0u8, 0) { + (x @ 0 | x @ (1 | 2), _) => {} + (3.., _) => {} + } } From ff3a818554a26c56c1ad0381307eed938b5bbbc5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 15:54:08 +0000 Subject: [PATCH 08/12] Poison check_well_formed if method receivers are invalid to prevent typeck from running on it --- .../rustc_hir_analysis/src/check/wfcheck.rs | 35 ++++++++++++------- ...ary-self-from-method-substs.default.stderr | 13 +++++++ ...ry-self-from-method-substs.feature.stderr} | 2 +- .../self/arbitrary-self-from-method-substs.rs | 8 +++-- 4 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 tests/ui/self/arbitrary-self-from-method-substs.default.stderr rename tests/ui/self/{arbitrary-self-from-method-substs.stderr => arbitrary-self-from-method-substs.feature.stderr} (80%) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3f31ce7aa58b7..046983e90f7b9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -94,7 +94,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( f: F, ) -> Result<(), ErrorGuaranteed> where - F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>), + F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>, { let param_env = tcx.param_env(body_def_id); let infcx = &tcx.infer_ctxt().build(); @@ -105,7 +105,7 @@ where if !tcx.features().trivial_bounds { wfcx.check_false_global_bounds() } - f(&mut wfcx); + f(&mut wfcx)?; let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; @@ -875,6 +875,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ty, trait_def_id, ); + Ok(()) }) } else { let mut diag = match ty.kind() { @@ -961,6 +962,7 @@ fn check_associated_item( let ty = tcx.type_of(item.def_id).instantiate_identity(); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); + Ok(()) } ty::AssocKind::Fn => { let sig = tcx.fn_sig(item.def_id).instantiate_identity(); @@ -972,7 +974,7 @@ fn check_associated_item( hir_sig.decl, item.def_id.expect_local(), ); - check_method_receiver(wfcx, hir_sig, item, self_ty); + check_method_receiver(wfcx, hir_sig, item, self_ty) } ty::AssocKind::Type => { if let ty::AssocItemContainer::TraitContainer = item.container { @@ -983,6 +985,7 @@ fn check_associated_item( let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); } + Ok(()) } } }) @@ -1097,6 +1100,7 @@ fn check_type_defn<'tcx>( } check_where_clauses(wfcx, item.span, item.owner_id.def_id); + Ok(()) }) } @@ -1121,7 +1125,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant } let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { - check_where_clauses(wfcx, item.span, def_id) + check_where_clauses(wfcx, item.span, def_id); + Ok(()) }); // Only check traits, don't check trait aliases @@ -1164,6 +1169,7 @@ fn check_item_fn( enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| { let sig = tcx.fn_sig(def_id).instantiate_identity(); check_fn_or_method(wfcx, ident.span, sig, decl, def_id); + Ok(()) }) } @@ -1218,6 +1224,7 @@ fn check_item_type( tcx.require_lang_item(LangItem::Sync, Some(ty_span)), ); } + Ok(()) }) } @@ -1276,6 +1283,7 @@ fn check_impl<'tcx>( } check_where_clauses(wfcx, item.span, item.owner_id.def_id); + Ok(()) }) } @@ -1548,11 +1556,11 @@ fn check_method_receiver<'tcx>( fn_sig: &hir::FnSig<'_>, method: ty::AssocItem, self_ty: Ty<'tcx>, -) { +) -> Result<(), ErrorGuaranteed> { let tcx = wfcx.tcx(); if !method.fn_has_self_parameter { - return; + return Ok(()); } let span = fn_sig.decl.inputs[0].span; @@ -1571,11 +1579,11 @@ fn check_method_receiver<'tcx>( if tcx.features().arbitrary_self_types { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. - e0307(tcx, span, receiver_ty); + return Err(e0307(tcx, span, receiver_ty)); } } else { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) { - if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { + return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; would have worked with `arbitrary_self_types`. feature_err( &tcx.sess.parse_sess, @@ -1587,16 +1595,17 @@ fn check_method_receiver<'tcx>( ), ) .help(HELP_FOR_SELF_TYPE) - .emit(); + .emit() } else { // Report error; would not have worked with `arbitrary_self_types`. - e0307(tcx, span, receiver_ty); - } + e0307(tcx, span, receiver_ty) + }); } } + Ok(()) } -fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) { +fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed { struct_span_err!( tcx.sess.diagnostic(), span, @@ -1605,7 +1614,7 @@ fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) { ) .note("type of `self` must be `Self` or a type that dereferences to it") .help(HELP_FOR_SELF_TYPE) - .emit(); + .emit() } /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr new file mode 100644 index 0000000000000..cbf5e6c541a39 --- /dev/null +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -0,0 +1,13 @@ +error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/arbitrary-self-from-method-substs.rs:8:43 + | +LL | fn get>(self: R) -> u32 { + | ^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr similarity index 80% rename from tests/ui/self/arbitrary-self-from-method-substs.stderr rename to tests/ui/self/arbitrary-self-from-method-substs.feature.stderr index 6c252fadf4657..7378d53c37387 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs.rs:14:5 + --> $DIR/arbitrary-self-from-method-substs.rs:16:5 | LL | foo.get::<&Foo>(); | ^^^ expected `&Foo`, found `Foo` diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs index 0f911a20842bc..004445dc32723 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.rs +++ b/tests/ui/self/arbitrary-self-from-method-substs.rs @@ -1,10 +1,12 @@ -#![feature(arbitrary_self_types)] +// revisions: default feature +#![cfg_attr(feature, feature(arbitrary_self_types))] use std::ops::Deref; struct Foo(u32); impl Foo { - fn get>(self: R) -> u32 { + fn get>(self: R) -> u32 { + //[default]~^ ERROR: `R` cannot be used as the type of `self` self.0 } } @@ -12,5 +14,5 @@ impl Foo { fn main() { let mut foo = Foo(1); foo.get::<&Foo>(); - //~^ ERROR mismatched types + //[feature]~^ ERROR mismatched types } From 224ddf8fd9ee1d30053ae55a5d9fd49711b53360 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 16:05:25 +0000 Subject: [PATCH 09/12] Only run panic tests on targets that can unwind --- tests/ui/coroutine/gen_block_panic.rs | 1 + tests/ui/coroutine/gen_block_panic.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/coroutine/gen_block_panic.rs b/tests/ui/coroutine/gen_block_panic.rs index 33e2b4b265a11..2da0eb512cc0b 100644 --- a/tests/ui/coroutine/gen_block_panic.rs +++ b/tests/ui/coroutine/gen_block_panic.rs @@ -1,5 +1,6 @@ //compile-flags: --edition 2024 -Zunstable-options // run-pass +// needs-unwind #![feature(gen_blocks)] fn main() { diff --git a/tests/ui/coroutine/gen_block_panic.stderr b/tests/ui/coroutine/gen_block_panic.stderr index 33d2a95cab8bc..a0a6d1063c458 100644 --- a/tests/ui/coroutine/gen_block_panic.stderr +++ b/tests/ui/coroutine/gen_block_panic.stderr @@ -1,5 +1,5 @@ warning: unreachable statement - --> $DIR/gen_block_panic.rs:9:9 + --> $DIR/gen_block_panic.rs:10:9 | LL | panic!("foo"); | ------------- any code following this expression is unreachable From 162443b32e49bfc30ef57e2e9f9c3ede0edea5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 17 Oct 2023 22:06:58 +0000 Subject: [PATCH 10/12] Detect when trait is implemented for type and suggest importing it Fix #57457. --- .../rustc_hir_typeck/src/method/suggest.rs | 56 +++++++++++++------ tests/ui/traits/item-privacy.stderr | 21 +++---- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3ed22e095e89c..12cc5ed2f1a55 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span}; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -192,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .span_if_local(def_id) .unwrap_or_else(|| self.tcx.def_span(def_id)); err.span_label(sp, format!("private {kind} defined here")); - self.suggest_valid_traits(&mut err, out_of_scope_traits); + self.suggest_valid_traits(&mut err, out_of_scope_traits, true); err.emit(); } @@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, valid_out_of_scope_traits: Vec, + explain: bool, ) -> bool { if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; @@ -2476,7 +2478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did)) .copied(); - err.help("items from traits can only be used if the trait is in scope"); + if explain { + err.help("items from traits can only be used if the trait is in scope"); + } let msg = format!( "the following {traits_are} implemented but not in scope; \ perhaps add a `use` for {one_of_them}:", @@ -2693,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if self.suggest_valid_traits(err, valid_out_of_scope_traits) { + if self.suggest_valid_traits(err, valid_out_of_scope_traits, true) { return; } @@ -2970,22 +2974,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (candidates, Vec::new()) }; + let impls_trait = |def_id: DefId| { + let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| { + if param.index == 0 { + rcvr_ty.into() + } else { + self.infcx.var_for_def(span, param) + } + }); + self.infcx + .type_implements_trait(def_id, args, self.param_env) + .must_apply_modulo_regions() + && param_type.is_none() + }; match &potential_candidates[..] { [] => {} [trait_info] if trait_info.def_id.is_local() => { - err.subdiagnostic(CandidateTraitNote { - span: self.tcx.def_span(trait_info.def_id), - trait_name: self.tcx.def_path_str(trait_info.def_id), - item_name, - action_or_ty: if trait_missing_method { - "NONE".to_string() - } else { - param_type.map_or_else( - || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. - ToString::to_string, - ) - }, - }); + if impls_trait(trait_info.def_id) { + self.suggest_valid_traits(err, vec![trait_info.def_id], false); + } else { + err.subdiagnostic(CandidateTraitNote { + span: self.tcx.def_span(trait_info.def_id), + trait_name: self.tcx.def_path_str(trait_info.def_id), + item_name, + action_or_ty: if trait_missing_method { + "NONE".to_string() + } else { + param_type.map_or_else( + || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. + ToString::to_string, + ) + }, + }); + } } trait_infos => { let mut msg = message(param_type.map_or_else( @@ -2993,6 +3014,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |param| format!("restrict type parameter `{param}` with"), )); for (i, trait_info) in trait_infos.iter().enumerate() { + if impls_trait(trait_info.def_id) { + self.suggest_valid_traits(err, vec![trait_info.def_id], false); + } msg.push_str(&format!( "\ncandidate #{}: `{}`", i + 1, diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index af2e076321219..9382673afe04a 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -8,11 +8,10 @@ LL | S.a(); | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope -note: `method::A` defines an item `a`, perhaps you need to implement it - --> $DIR/item-privacy.rs:6:5 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL + use method::A; | -LL | trait A { - | ^^^^^^^ error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/item-privacy.rs:68:7 @@ -51,11 +50,10 @@ LL | S::a(&S); | ^ function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope -note: `method::A` defines an item `a`, perhaps you need to implement it - --> $DIR/item-privacy.rs:6:5 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL + use method::A; | -LL | trait A { - | ^^^^^^^ error[E0599]: no function or associated item named `b` found for struct `S` in the current scope --> $DIR/item-privacy.rs:80:8 @@ -91,11 +89,10 @@ LL | S::A; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope -note: `assoc_const::A` defines an item `A`, perhaps you need to implement it - --> $DIR/item-privacy.rs:24:5 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL + use assoc_const::A; | -LL | trait A { - | ^^^^^^^ error[E0599]: no associated item named `B` found for struct `S` in the current scope --> $DIR/item-privacy.rs:98:8 From 455cf5a4f6531598d72a7590c6f390d9296cc548 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 30 Oct 2023 17:47:07 +0000 Subject: [PATCH 11/12] Improve some diagnostics around `?Trait` bounds --- .../rustc_hir_analysis/src/astconv/bounds.rs | 57 ++++++++++--------- compiler/rustc_hir_analysis/src/errors.rs | 2 +- tests/ui/issues/issue-37534.rs | 6 +- tests/ui/issues/issue-37534.stderr | 12 ++-- tests/ui/issues/issue-87199.rs | 6 +- tests/ui/issues/issue-87199.stderr | 18 +++--- tests/ui/unsized/maybe-bounds-where.rs | 4 +- tests/ui/unsized/maybe-bounds-where.stderr | 16 +++--- 8 files changed, 63 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 711da6db5accb..3e700f2da8696 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; +use smallvec::SmallVec; use crate::astconv::{ AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter, @@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); // Try to find an unbound in bounds. - let mut unbound = None; + let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { for ab in ast_bounds { if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span }); - } + unbounds.push(ptr) } } }; @@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } } + if unbounds.len() > 1 { + tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { + spans: unbounds.iter().map(|ptr| ptr.span).collect(), + }); + } + let sized_def_id = tcx.lang_items().sized_trait(); - match (&sized_def_id, unbound) { - (Some(sized_def_id), Some(tpb)) - if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => - { - // There was in fact a `?Sized` bound, return without doing anything - return; - } - (_, Some(_)) => { - // There was a `?Trait` bound, but it was not `?Sized`; warn. - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - // Otherwise, add implicitly sized if `Sized` is available. - } - _ => { - // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + + let mut seen_sized_unbound = false; + for unbound in unbounds { + if let Some(sized_def_id) = sized_def_id { + if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) { + seen_sized_unbound = true; + continue; + } } + // There was a `?Trait` bound, but it was not `?Sized`; warn. + tcx.sess.span_warn( + unbound.span, + "relaxing a default bound only does something for `?Sized`; \ + all other traits are not bound by default", + ); } + + // If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available. if sized_def_id.is_none() { // No lang item for `Sized`, so we can't add it as a bound. return; } - bounds.push_sized(tcx, self_ty, span); + if seen_sized_unbound { + // There was in fact a `?Sized` bound, return without doing anything + } else { + // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + bounds.push_sized(tcx, self_ty, span); + } } /// This helper takes a *converted* parameter type (`param_ty`) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a2db1d06276c..dd83b5b6f2c03 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -96,7 +96,7 @@ pub struct CopyImplOnTypeWithDtor { #[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")] pub struct MultipleRelaxedDefaultBounds { #[primary_span] - pub span: Span, + pub spans: Vec, } #[derive(Diagnostic)] diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs index 1e67e9a815830..40f7186db098e 100644 --- a/tests/ui/issues/issue-37534.rs +++ b/tests/ui/issues/issue-37534.rs @@ -1,6 +1,6 @@ -struct Foo { } +struct Foo {} //~^ ERROR expected trait, found derive macro `Hash` //~^^ ERROR parameter `T` is never used -//~^^^ WARN default bound relaxed for a type parameter, but this does nothing +//~^^^ WARN relaxing a default bound only does something for `?Sized` -fn main() { } +fn main() {} diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr index 7d3dd8800bd34..03fea2c16486d 100644 --- a/tests/ui/issues/issue-37534.stderr +++ b/tests/ui/issues/issue-37534.stderr @@ -1,7 +1,7 @@ error[E0404]: expected trait, found derive macro `Hash` --> $DIR/issue-37534.rs:1:16 | -LL | struct Foo { } +LL | struct Foo {} | ^^^^ not a trait | help: consider importing this trait instead @@ -9,16 +9,16 @@ help: consider importing this trait instead LL + use std::hash::Hash; | -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/issue-37534.rs:1:12 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/issue-37534.rs:1:15 | -LL | struct Foo { } - | ^ +LL | struct Foo {} + | ^^^^^ error[E0392]: parameter `T` is never used --> $DIR/issue-37534.rs:1:12 | -LL | struct Foo { } +LL | struct Foo {} | ^ unused parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs index a80a64a2f87ee..d16d406767300 100644 --- a/tests/ui/issues/issue-87199.rs +++ b/tests/ui/issues/issue-87199.rs @@ -6,11 +6,11 @@ // Check that these function definitions only emit warnings, not errors fn arg(_: T) {} -//~^ warning: default bound relaxed for a type parameter, but this does nothing +//~^ warning: relaxing a default bound only does something for `?Sized` fn ref_arg(_: &T) {} -//~^ warning: default bound relaxed for a type parameter, but this does nothing +//~^ warning: relaxing a default bound only does something for `?Sized` fn ret() -> impl Iterator + ?Send { std::iter::empty() } -//~^ warning: default bound relaxed for a type parameter, but this does nothing +//~^ warning: relaxing a default bound only does something for `?Sized` // Check that there's no `?Sized` relaxation! fn main() { diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index 67949b37d4099..e02cd7fcfa9e4 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -1,20 +1,20 @@ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/issue-87199.rs:8:8 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/issue-87199.rs:8:11 | LL | fn arg(_: T) {} - | ^ + | ^^^^^ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/issue-87199.rs:10:12 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/issue-87199.rs:10:15 | LL | fn ref_arg(_: &T) {} - | ^ + | ^^^^^ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/issue-87199.rs:12:13 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/issue-87199.rs:12:40 | LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/issue-87199.rs:18:15 diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/maybe-bounds-where.rs index d7af0c4248056..7e82a3eb449cb 100644 --- a/tests/ui/unsized/maybe-bounds-where.rs +++ b/tests/ui/unsized/maybe-bounds-where.rs @@ -11,11 +11,11 @@ trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared -//~| WARN default bound relaxed for a type parameter +//~| WARN relaxing a default bound only does something for `?Sized` struct S5(*const T) where T: ?Trait<'static> + ?Sized; //~^ ERROR type parameter has more than one relaxed default bound -//~| WARN default bound relaxed for a type parameter +//~| WARN relaxing a default bound only does something for `?Sized` impl S1 { fn f() where T: ?Sized {} diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr index 39bc1b88e56d7..683bd387bb292 100644 --- a/tests/ui/unsized/maybe-bounds-where.stderr +++ b/tests/ui/unsized/maybe-bounds-where.stderr @@ -28,23 +28,23 @@ error: `?Trait` bounds are only permitted at the point where a type parameter is LL | fn f() where T: ?Sized {} | ^^^^^^ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/maybe-bounds-where.rs:12:11 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/maybe-bounds-where.rs:12:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; - | ^ + | ^^^^^^^^^^ error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-bounds-where.rs:16:11 + --> $DIR/maybe-bounds-where.rs:16:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; - | ^ + | ^^^^^^^^^^^^^^^ ^^^^^^ -warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/maybe-bounds-where.rs:16:11 +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/maybe-bounds-where.rs:16:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; - | ^ + | ^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors; 2 warnings emitted From c91f60e22fccbd1ee7701b2a1b88457985f9df0b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Oct 2023 19:24:08 +0000 Subject: [PATCH 12/12] Don't super-fold types when we hit the recursion limit --- .../src/traits/query/normalize.rs | 11 ++++------- .../infinite-cycle-involving-weak.rs | 8 ++++++++ .../infinite-cycle-involving-weak.stderr | 9 +++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs create mode 100644 tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index c761d0d103ea2..2e31b560b38ff 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -230,17 +230,14 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> Reveal::All => { let args = data.args.try_fold_with(self)?; let recursion_limit = self.interner().recursion_limit(); + if !recursion_limit.value_within_limit(self.anon_depth) { - // A closure or coroutine may have itself as in its upvars. - // This should be checked handled by the recursion check for opaque - // types, but we may end up here before that check can happen. - // In that case, we delay a bug to mark the trip, and continue without - // revealing the opaque. - self.infcx + let guar = self + .infcx .err_ctxt() .build_overflow_error(&ty, self.cause.span, true) .delay_as_bug(); - return ty.try_super_fold_with(self); + return Ok(Ty::new_error(self.interner(), guar)); } let generic_ty = self.interner().type_of(data.def_id); diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs new file mode 100644 index 0000000000000..6609d4eb5a274 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs @@ -0,0 +1,8 @@ +#![feature(type_alias_impl_trait)] + +type T = impl Copy; +//~^ ERROR cannot resolve opaque type + +static STATIC: T = None::<&'static T>; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr new file mode 100644 index 0000000000000..50ae6f3864112 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr @@ -0,0 +1,9 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/infinite-cycle-involving-weak.rs:3:10 + | +LL | type T = impl Copy; + | ^^^^^^^^^ cannot resolve opaque type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`.