diff options
20 files changed, 191 insertions, 70 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddeb489c647..5f14cd36ce4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -382,6 +382,7 @@ jobs: - name: x86_64-msvc-ext env: SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + HOST_TARGET: x86_64-pc-windows-msvc RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json" DEPLOY_TOOLSTATES_JSON: toolstates-windows.json os: windows-2019-8core-32gb diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3ed22e095e8..12cc5ed2f1a 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<DefId>, + 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/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 37ff5bcf1e2..27d555d7e26 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 c2aa015f4b7..9dfbe1733cc 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -250,8 +250,7 @@ impl<O> AssertKind<O> { 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/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 25e0f3ceaa4..59f0849d08b 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/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 9bedd7b8a33..9ba1f0a5df9 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 c0e94d15da0..e5cd91a32a7 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 a9f456d64cd..55ad3f42938 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/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index f7d54566cb7..9242a1a751b 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<TyCtxt<'tcx>>) -> 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 1ab39974e0f..ccdc6120196 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()); @@ -61,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)?; } @@ -74,13 +59,15 @@ 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)?; } } - // 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; @@ -94,13 +81,9 @@ 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::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)?; } diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 85f2f84a44c..b0eeff0c576 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -83,6 +83,8 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --save-toolstates=/tmp/toolstate/toolstates.json +ENV HOST_TARGET x86_64-unknown-linux-gnu + ENV SCRIPT /tmp/checktools.sh ../x.py && \ NODE_PATH=`npm root -g` python3 ../x.py test tests/rustdoc-gui --stage 2 \ --test-args "'--no-sandbox --jobs 1'" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index 7dde6370904..821a09feb2d 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -1,4 +1,5 @@ #!/bin/sh +# ignore-tidy-linelength set -eu @@ -26,8 +27,30 @@ python3 "$X_PY" test --stage 2 src/tools/clippy python3 "$X_PY" test --stage 2 src/tools/rustfmt python3 "$X_PY" test --stage 2 src/tools/miri # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc. -# Also cover some other targets (on both of these hosts) via cross-testing. +# Also cover some other targets via cross-testing, in particular all tier 1 targets. export BOOTSTRAP_SKIP_TARGET_SANITY=1 # we don't need `cc` for these targets -python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc -python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin +case $HOST_TARGET in + x86_64-unknown-linux-gnu) + # Only this branch runs in PR CI. + # Fully test all main OSes, including a 32bit target. + python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-apple-darwin + python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc + # Only run "pass" tests for the remaining targets, which is quite a bit faster. + python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass + python3 "$X_PY" test --stage 2 src/tools/miri --target i686-unknown-linux-gnu --test-args pass + python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-unknown-linux-gnu --test-args pass + python3 "$X_PY" test --stage 2 src/tools/miri --target s390x-unknown-linux-gnu --test-args pass + ;; + x86_64-pc-windows-msvc) + # Strangely, Linux targets do not work here. cargo always says + # "error: cannot produce cdylib for ... as the target ... does not support these crate types". + # Only run "pass" tests, which is quite a bit faster. + python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass + python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass + ;; + *) + echo "FATAL: unexpected host $HOST_TARGET" + exit 1 + ;; +esac unset BOOTSTRAP_SKIP_TARGET_SANITY diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index bbba6600581..2feb51920df 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -582,6 +582,7 @@ jobs: - name: x86_64-msvc-ext env: SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + HOST_TARGET: x86_64-pc-windows-msvc RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json DEPLOY_TOOLSTATES_JSON: toolstates-windows.json <<: *job-windows-8c diff --git a/tests/ui/coroutine/gen_block_panic.rs b/tests/ui/coroutine/gen_block_panic.rs new file mode 100644 index 00000000000..2da0eb512cc --- /dev/null +++ b/tests/ui/coroutine/gen_block_panic.rs @@ -0,0 +1,26 @@ +//compile-flags: --edition 2024 -Zunstable-options +// run-pass +// needs-unwind +#![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 00000000000..a0a6d1063c4 --- /dev/null +++ b/tests/ui/coroutine/gen_block_panic.stderr @@ -0,0 +1,12 @@ +warning: unreachable statement + --> $DIR/gen_block_panic.rs:10: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 + diff --git a/tests/ui/coroutine/gen_fn.e2024.stderr b/tests/ui/coroutine/gen_fn.e2024.stderr index 41bd04d9769..388e10fd65e 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 9566660dfb5..da515f263b0 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() {} diff --git a/tests/ui/or-patterns/exhaustiveness-pass.rs b/tests/ui/or-patterns/exhaustiveness-pass.rs index e8c8a0e7ba5..428b9a19fe6 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.., _) => {} + } } diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index af2e0763212..9382673afe0 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 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 00000000000..5f3dbaa1798 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_impl_trait_in_assoc_ty.rs @@ -0,0 +1,44 @@ +//! 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)] + +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<Output = Self::IterStream<'_>> + '_ { + async move { merge_stream(self.mem_table.iter()) } + } +} + +trait LocalStateStore { + type IterStream<'a> + where + Self: 'a; + + fn iter(&self) -> impl Future<Output = Self::IterStream<'_>> + '_; +} + +struct MemTable; + +impl MemTable { + fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ()> { + std::iter::empty() + } +} + +pub(crate) async fn merge_stream<'a>(mem_table_iter: impl Iterator<Item = &'a ()>) {} + +fn main() {} |
