From 1b0c0eb717fc5457ec1881c6310f7d7c25ba0d19 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 15 Jan 2022 14:23:45 +0100 Subject: [PATCH 1/7] Deny mixing bin crate type with lib crate types The produced library would get a main shim too which conflicts with the main shim of the executable linking the library. ``` $ cat > main1.rs < main2.rs < ast::Crate { let ecfg = ExpansionConfig::default("proc_macro".to_string()); @@ -81,10 +80,6 @@ pub fn inject( return krate; } - if num_crate_types > 1 { - handler.err("cannot mix `proc-macro` crate type with others"); - } - if is_test_crate { return krate; } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 33bf670f570f8..34e619540d272 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -382,8 +382,18 @@ pub fn configure_and_expand( }); let crate_types = sess.crate_types(); + let is_executable_crate = crate_types.contains(&CrateType::Executable); let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); + if crate_types.len() > 1 { + if is_executable_crate { + sess.err("cannot mix `bin` crate type with others"); + } + if is_proc_macro_crate { + sess.err("cannot mix `proc-macro` crate type with others"); + } + } + // For backwards compatibility, we don't try to run proc macro injection // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being // specified. This should only affect users who manually invoke 'rustdoc', as @@ -400,7 +410,6 @@ pub fn configure_and_expand( msg.emit() } else { krate = sess.time("maybe_create_a_macro_crate", || { - let num_crate_types = crate_types.len(); let is_test_crate = sess.opts.test; rustc_builtin_macros::proc_macro_harness::inject( sess, @@ -409,7 +418,6 @@ pub fn configure_and_expand( is_proc_macro_crate, has_proc_macro_decls, is_test_crate, - num_crate_types, sess.diagnostic(), ) }); From 0b5963023d9d3bdbbf27e9f92171047cf2a7f008 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 15 Jan 2022 15:43:02 +0100 Subject: [PATCH 2/7] Update tests --- src/test/run-make-fulldeps/libs-and-bins/Makefile | 6 ------ src/test/run-make-fulldeps/libs-and-bins/foo.rs | 4 ---- src/test/run-make-fulldeps/output-with-hyphens/Makefile | 3 ++- src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs | 3 --- 4 files changed, 2 insertions(+), 14 deletions(-) delete mode 100644 src/test/run-make-fulldeps/libs-and-bins/Makefile delete mode 100644 src/test/run-make-fulldeps/libs-and-bins/foo.rs diff --git a/src/test/run-make-fulldeps/libs-and-bins/Makefile b/src/test/run-make-fulldeps/libs-and-bins/Makefile deleted file mode 100644 index cc3b257a5c5bf..0000000000000 --- a/src/test/run-make-fulldeps/libs-and-bins/Makefile +++ /dev/null @@ -1,6 +0,0 @@ --include ../tools.mk - -all: - $(RUSTC) foo.rs - $(call RUN,foo) - rm $(TMPDIR)/$(call DYLIB_GLOB,foo) diff --git a/src/test/run-make-fulldeps/libs-and-bins/foo.rs b/src/test/run-make-fulldeps/libs-and-bins/foo.rs deleted file mode 100644 index ae166b17840e3..0000000000000 --- a/src/test/run-make-fulldeps/libs-and-bins/foo.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![crate_type = "dylib"] -#![crate_type = "bin"] - -fn main() {} diff --git a/src/test/run-make-fulldeps/output-with-hyphens/Makefile b/src/test/run-make-fulldeps/output-with-hyphens/Makefile index 783d826a53dab..69a286f0b74f8 100644 --- a/src/test/run-make-fulldeps/output-with-hyphens/Makefile +++ b/src/test/run-make-fulldeps/output-with-hyphens/Makefile @@ -1,6 +1,7 @@ -include ../tools.mk all: - $(RUSTC) foo-bar.rs + $(RUSTC) foo-bar.rs --crate-type bin [ -f $(TMPDIR)/$(call BIN,foo-bar) ] + $(RUSTC) foo-bar.rs --crate-type lib [ -f $(TMPDIR)/libfoo_bar.rlib ] diff --git a/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs b/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs index 3f1a70458e377..f328e4d9d04c3 100644 --- a/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs +++ b/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs @@ -1,4 +1 @@ -#![crate_type = "lib"] -#![crate_type = "bin"] - fn main() {} From 6d05e2a9afb558e4e9668e54db6747e4d8a8383a Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sat, 15 Jan 2022 04:16:13 -0500 Subject: [PATCH 3/7] add more info to invalid use of #[test] on invalid items --- compiler/rustc_builtin_macros/src/test.rs | 22 ++- src/test/ui/issues/issue-14772.rs | 6 - src/test/ui/issues/issue-14772.stderr | 8 - src/test/ui/test-attrs/test-on-macro.rs | 13 -- src/test/ui/test-attrs/test-on-macro.stderr | 8 - src/test/ui/test-attrs/test-on-not-fn.rs | 80 ++++++++ src/test/ui/test-attrs/test-on-not-fn.stderr | 185 +++++++++++++++++++ 7 files changed, 281 insertions(+), 41 deletions(-) delete mode 100644 src/test/ui/issues/issue-14772.rs delete mode 100644 src/test/ui/issues/issue-14772.stderr delete mode 100644 src/test/ui/test-attrs/test-on-macro.rs delete mode 100644 src/test/ui/test-attrs/test-on-macro.stderr create mode 100644 src/test/ui/test-attrs/test-on-not-fn.rs create mode 100644 src/test/ui/test-attrs/test-on-not-fn.stderr diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index c08b141b557ca..97cb7aa0ddeb1 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -6,6 +6,7 @@ use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast_pretty::pprust; +use rustc_errors::Applicability; use rustc_expand::base::*; use rustc_session::Session; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -102,11 +103,20 @@ pub fn expand_test_or_bench( } }; - if let ast::ItemKind::MacCall(_) = item.kind { - cx.sess.parse_sess.span_diagnostic.span_warn( - item.span, - "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.", - ); + // Note: non-associated fn items are already handled by `expand_test_or_bench` + if !matches!(item.kind, ast::ItemKind::Fn(_)) { + cx.sess + .parse_sess + .span_diagnostic + .struct_span_err( + attr_sp, + "the `#[test]` attribute may only be used on a non-associated function", + ) + .note("the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions") + .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr())) + .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect) + .emit(); + return vec![Annotatable::Item(item)]; } @@ -475,7 +485,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { (false, _) => true, } } else { - sd.span_err(i.span, "only functions may be used as tests"); + // should be unreachable because `is_test_fn_item` should catch all non-fn items false } } diff --git a/src/test/ui/issues/issue-14772.rs b/src/test/ui/issues/issue-14772.rs deleted file mode 100644 index 8f6745246fd1d..0000000000000 --- a/src/test/ui/issues/issue-14772.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags: --test - -#[test] -mod foo {} //~ ERROR only functions may be used as tests - -fn main() {} diff --git a/src/test/ui/issues/issue-14772.stderr b/src/test/ui/issues/issue-14772.stderr deleted file mode 100644 index 253fec5e57833..0000000000000 --- a/src/test/ui/issues/issue-14772.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: only functions may be used as tests - --> $DIR/issue-14772.rs:4:1 - | -LL | mod foo {} - | ^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/test-attrs/test-on-macro.rs b/src/test/ui/test-attrs/test-on-macro.rs deleted file mode 100644 index 0667364d13cd4..0000000000000 --- a/src/test/ui/test-attrs/test-on-macro.rs +++ /dev/null @@ -1,13 +0,0 @@ -// check-pass -// compile-flags:--test - -#![deny(warnings)] - -macro_rules! foo { - () => (fn foo(){}) -} - -#[test] -foo!(); //~ WARNING `#[test]` attribute should not be used on macros - -fn main(){} diff --git a/src/test/ui/test-attrs/test-on-macro.stderr b/src/test/ui/test-attrs/test-on-macro.stderr deleted file mode 100644 index 98190b060cec5..0000000000000 --- a/src/test/ui/test-attrs/test-on-macro.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: `#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead. - --> $DIR/test-on-macro.rs:11:1 - | -LL | foo!(); - | ^^^^^^^ - -warning: 1 warning emitted - diff --git a/src/test/ui/test-attrs/test-on-not-fn.rs b/src/test/ui/test-attrs/test-on-not-fn.rs new file mode 100644 index 0000000000000..b2f681c01d156 --- /dev/null +++ b/src/test/ui/test-attrs/test-on-not-fn.rs @@ -0,0 +1,80 @@ +// compile-flags: --test + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +mod test {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +mod loooooooooooooong_teeeeeeeeeest { + /* + this is a comment + this comment goes on for a very long time + this is to pad out the span for this module for a long time + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in + voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + */ +} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +extern "C" {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +trait Foo {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +impl Foo for i32 {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +const FOO: i32 = -1_i32; + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +static BAR: u64 = 10_000_u64; + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +enum MyUnit { + Unit, +} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +struct NewI32(i32); + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +union Spooky { + x: i32, + y: u32, +} + +#[repr(C, align(64))] +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +#[derive(Copy, Clone, Debug)] +struct MoreAttrs { + a: i32, + b: u64, +} + +macro_rules! foo { + () => {}; +} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +foo!(); + +// make sure it doesn't erroneously trigger on a real test +#[test] +fn real_test() { + assert_eq!(42_i32, 42_i32); +} + +// make sure it works with cfg test +#[cfg(test)] +mod real_tests { + #[cfg(test)] + fn foo() {} + + #[test] + fn bar() { + foo(); + } +} diff --git a/src/test/ui/test-attrs/test-on-not-fn.stderr b/src/test/ui/test-attrs/test-on-not-fn.stderr new file mode 100644 index 0000000000000..dd693cf316dc7 --- /dev/null +++ b/src/test/ui/test-attrs/test-on-not-fn.stderr @@ -0,0 +1,185 @@ +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:3:1 + | +LL | #[test] + | ^^^^^^^ +LL | mod test {} + | ----------- expected a non-associated function, found a module + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:6:1 + | +LL | #[test] + | ^^^^^^^ +LL | / mod loooooooooooooong_teeeeeeeeeest { +LL | | /* +LL | | this is a comment +LL | | this comment goes on for a very long time +... | +LL | | */ +LL | | } + | |_- expected a non-associated function, found a module + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:20:1 + | +LL | #[test] + | ^^^^^^^ +LL | extern "C" {} + | ------------- expected a non-associated function, found an extern block + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:23:1 + | +LL | #[test] + | ^^^^^^^ +LL | trait Foo {} + | ------------ expected a non-associated function, found a trait + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:26:1 + | +LL | #[test] + | ^^^^^^^ +LL | impl Foo for i32 {} + | ------------------- expected a non-associated function, found an implementation + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:29:1 + | +LL | #[test] + | ^^^^^^^ +LL | const FOO: i32 = -1_i32; + | ------------------------ expected a non-associated function, found a constant item + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:32:1 + | +LL | #[test] + | ^^^^^^^ +LL | static BAR: u64 = 10_000_u64; + | ----------------------------- expected a non-associated function, found a static item + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:35:1 + | +LL | #[test] + | ^^^^^^^ +LL | / enum MyUnit { +LL | | Unit, +LL | | } + | |_- expected a non-associated function, found an enum + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:40:1 + | +LL | #[test] + | ^^^^^^^ +LL | struct NewI32(i32); + | ------------------- expected a non-associated function, found a struct + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:43:1 + | +LL | #[test] + | ^^^^^^^ +LL | / union Spooky { +LL | | x: i32, +LL | | y: u32, +LL | | } + | |_- expected a non-associated function, found a union + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:50:1 + | +LL | #[test] + | ^^^^^^^ +LL | #[derive(Copy, Clone, Debug)] +LL | / struct MoreAttrs { +LL | | a: i32, +LL | | b: u64, +LL | | } + | |_- expected a non-associated function, found a struct + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:61:1 + | +LL | #[test] + | ^^^^^^^ +LL | foo!(); + | ------- expected a non-associated function, found an item macro invocation + | + = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: aborting due to 12 previous errors + From b651d5a1f4b3b8ab54926d4f5dd0390a94f5bac3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Jan 2022 20:38:38 -0800 Subject: [PATCH 4/7] Fix Inline MIR pass on a function with un-satisfiable bounds --- compiler/rustc_mir_transform/src/inline.rs | 13 +++++++++++-- .../rustc_trait_selection/src/traits/codegen.rs | 2 ++ src/test/ui/trait-bounds/issue-93008.rs | 10 ++++++++++ src/test/ui/trait-bounds/issue-93008.stderr | 12 ++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/trait-bounds/issue-93008.rs create mode 100644 src/test/ui/trait-bounds/issue-93008.stderr diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e1f30fef44f99..6220daa0b6b0f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -7,6 +7,7 @@ use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_span::{hygiene::ExpnKind, ExpnData, Span}; @@ -75,10 +76,18 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { return false; } + let param_env = tcx.param_env_reveal_all_normalized(def_id); + let param_env = rustc_trait_selection::traits::normalize_param_env_or_error( + tcx, + def_id, + param_env, + ObligationCause::misc(body.span, hir_id), + ); + let mut this = Inliner { tcx, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), - codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()), + param_env, + codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), hir_id, history: Vec::new(), changed: false, diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 848aba7c91289..a0c60898c156c 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -65,6 +65,8 @@ pub fn codegen_fulfill_obligation<'tcx>( Err(Unimplemented) => { // This can trigger when we probe for the source of a `'static` lifetime requirement // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound. + // This can also trigger when we have a global bound that is not actually satisfied, + // but was included during typeck due to the trivial_bounds feature. infcx.tcx.sess.delay_span_bug( rustc_span::DUMMY_SP, &format!( diff --git a/src/test/ui/trait-bounds/issue-93008.rs b/src/test/ui/trait-bounds/issue-93008.rs new file mode 100644 index 0000000000000..1b010566cbc6e --- /dev/null +++ b/src/test/ui/trait-bounds/issue-93008.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zmir-opt-level=4 + +pub fn bar(s: &'static mut ()) +where + &'static mut (): Clone, //~ ERROR the trait bound +{ + <&'static mut () as Clone>::clone(&s); +} + +fn main() {} diff --git a/src/test/ui/trait-bounds/issue-93008.stderr b/src/test/ui/trait-bounds/issue-93008.stderr new file mode 100644 index 0000000000000..10f80f8de0c9b --- /dev/null +++ b/src/test/ui/trait-bounds/issue-93008.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&'static mut (): Clone` is not satisfied + --> $DIR/issue-93008.rs:5:5 + | +LL | &'static mut (): Clone, + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&'static mut ()` + | + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 18130a21dc8744c9a1f734016e0b399d70e8f968 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Thu, 3 Feb 2022 17:56:10 +0800 Subject: [PATCH 5/7] Move `{core,std}::stream::Stream` to `{core,std}::async_iter::AsyncIterator`. --- library/alloc/src/boxed.rs | 6 +- library/alloc/src/lib.rs | 2 +- .../stream.rs => async_iter/async_iter.rs} | 56 +++++++-------- .../src/{stream => async_iter}/from_iter.rs | 18 ++--- .../core/src/{stream => async_iter}/mod.rs | 69 +++++++++---------- library/core/src/lib.rs | 4 +- library/core/src/panic/unwind_safe.rs | 6 +- library/std/src/lib.rs | 6 +- 8 files changed, 83 insertions(+), 84 deletions(-) rename library/core/src/{stream/stream.rs => async_iter/async_iter.rs} (61%) rename library/core/src/{stream => async_iter}/from_iter.rs (54%) rename library/core/src/{stream => async_iter}/mod.rs (56%) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index aa7344ba405a9..68bf59a01b3dd 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -133,6 +133,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::any::Any; +use core::async_iter::AsyncIterator; use core::borrow; use core::cmp::Ordering; use core::convert::{From, TryFrom}; @@ -149,7 +150,6 @@ use core::ops::{ }; use core::pin::Pin; use core::ptr::{self, Unique}; -use core::stream::Stream; use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] @@ -1992,8 +1992,8 @@ where } } -#[unstable(feature = "async_stream", issue = "79024")] -impl Stream for Box { +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for Box { type Item = S::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index dfd3771c1d042..5f866cc5f7863 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -91,7 +91,7 @@ #![feature(array_chunks)] #![feature(array_methods)] #![feature(array_windows)] -#![feature(async_stream)] +#![feature(async_iterator)] #![feature(coerce_unsized)] #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![feature(const_box)] diff --git a/library/core/src/stream/stream.rs b/library/core/src/async_iter/async_iter.rs similarity index 61% rename from library/core/src/stream/stream.rs rename to library/core/src/async_iter/async_iter.rs index 2cfddf9ad013d..f29de31171a67 100644 --- a/library/core/src/stream/stream.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -4,50 +4,50 @@ use crate::task::{Context, Poll}; /// An interface for dealing with asynchronous iterators. /// -/// This is the main stream trait. For more about the concept of streams +/// This is the main async iterator trait. For more about the concept of async iterators /// generally, please see the [module-level documentation]. In particular, you -/// may want to know how to [implement `Stream`][impl]. +/// may want to know how to [implement `AsyncIterator`][impl]. /// /// [module-level documentation]: index.html -/// [impl]: index.html#implementing-stream -#[unstable(feature = "async_stream", issue = "79024")] -#[must_use = "streams do nothing unless polled"] -pub trait Stream { - /// The type of items yielded by the stream. +/// [impl]: index.html#implementing-async-iterator +#[unstable(feature = "async_iterator", issue = "79024")] +#[must_use = "async iterators do nothing unless polled"] +pub trait AsyncIterator { + /// The type of items yielded by the async iterator. type Item; - /// Attempt to pull out the next value of this stream, registering the + /// Attempt to pull out the next value of this async iterator, registering the /// current task for wakeup if the value is not yet available, and returning - /// `None` if the stream is exhausted. + /// `None` if the async iterator is exhausted. /// /// # Return value /// /// There are several possible return values, each indicating a distinct - /// stream state: + /// async iterator state: /// - /// - `Poll::Pending` means that this stream's next value is not ready + /// - `Poll::Pending` means that this async iterator's next value is not ready /// yet. Implementations will ensure that the current task will be notified /// when the next value may be ready. /// - /// - `Poll::Ready(Some(val))` means that the stream has successfully + /// - `Poll::Ready(Some(val))` means that the async iterator has successfully /// produced a value, `val`, and may produce further values on subsequent /// `poll_next` calls. /// - /// - `Poll::Ready(None)` means that the stream has terminated, and + /// - `Poll::Ready(None)` means that the async iterator has terminated, and /// `poll_next` should not be invoked again. /// /// # Panics /// - /// Once a stream has finished (returned `Ready(None)` from `poll_next`), calling its + /// Once an async iterator has finished (returned `Ready(None)` from `poll_next`), calling its /// `poll_next` method again may panic, block forever, or cause other kinds of - /// problems; the `Stream` trait places no requirements on the effects of + /// problems; the `AsyncIterator` trait places no requirements on the effects of /// such a call. However, as the `poll_next` method is not marked `unsafe`, /// Rust's usual rules apply: calls must never cause undefined behavior /// (memory corruption, incorrect use of `unsafe` functions, or the like), - /// regardless of the stream's state. + /// regardless of the async iterator's state. fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - /// Returns the bounds on the remaining length of the stream. + /// Returns the bounds on the remaining length of the async iterator. /// /// Specifically, `size_hint()` returns a tuple where the first element /// is the lower bound, and the second element is the upper bound. @@ -58,12 +58,12 @@ pub trait Stream { /// /// # Implementation notes /// - /// It is not enforced that a stream implementation yields the declared - /// number of elements. A buggy stream may yield less than the lower bound + /// It is not enforced that an async iterator implementation yields the declared + /// number of elements. A buggy async iterator may yield less than the lower bound /// or more than the upper bound of elements. /// /// `size_hint()` is primarily intended to be used for optimizations such as - /// reserving space for the elements of the stream, but must not be + /// reserving space for the elements of the async iterator, but must not be /// trusted to e.g., omit bounds checks in unsafe code. An incorrect /// implementation of `size_hint()` should not lead to memory safety /// violations. @@ -72,15 +72,15 @@ pub trait Stream { /// because otherwise it would be a violation of the trait's protocol. /// /// The default implementation returns (0, [None]) which is correct for any - /// stream. + /// async iterator. #[inline] fn size_hint(&self) -> (usize, Option) { (0, None) } } -#[unstable(feature = "async_stream", issue = "79024")] -impl Stream for &mut S { +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for &mut S { type Item = S::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -92,16 +92,16 @@ impl Stream for &mut S { } } -#[unstable(feature = "async_stream", issue = "79024")] -impl

Stream for Pin

+#[unstable(feature = "async_iterator", issue = "79024")] +impl

AsyncIterator for Pin

where P: DerefMut, - P::Target: Stream, + P::Target: AsyncIterator, { - type Item = ::Item; + type Item = ::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - ::poll_next(self.as_deref_mut(), cx) + ::poll_next(self.as_deref_mut(), cx) } fn size_hint(&self) -> (usize, Option) { diff --git a/library/core/src/stream/from_iter.rs b/library/core/src/async_iter/from_iter.rs similarity index 54% rename from library/core/src/stream/from_iter.rs rename to library/core/src/async_iter/from_iter.rs index eb9a0fd284257..3180187afc8c9 100644 --- a/library/core/src/stream/from_iter.rs +++ b/library/core/src/async_iter/from_iter.rs @@ -1,31 +1,31 @@ use crate::pin::Pin; -use crate::stream::Stream; +use crate::async_iter::AsyncIterator; use crate::task::{Context, Poll}; -/// A stream that was created from iterator. +/// An async iterator that was created from iterator. /// -/// This stream is created by the [`from_iter`] function. +/// This async iterator is created by the [`from_iter`] function. /// See it documentation for more. /// /// [`from_iter`]: fn.from_iter.html -#[unstable(feature = "stream_from_iter", issue = "81798")] +#[unstable(feature = "async_iter_from_iter", issue = "81798")] #[derive(Clone, Debug)] pub struct FromIter { iter: I, } -#[unstable(feature = "stream_from_iter", issue = "81798")] +#[unstable(feature = "async_iter_from_iter", issue = "81798")] impl Unpin for FromIter {} -/// Converts an iterator into a stream. -#[unstable(feature = "stream_from_iter", issue = "81798")] +/// Converts an iterator into an async iterator. +#[unstable(feature = "async_iter_from_iter", issue = "81798")] pub fn from_iter(iter: I) -> FromIter { FromIter { iter: iter.into_iter() } } -#[unstable(feature = "stream_from_iter", issue = "81798")] -impl Stream for FromIter { +#[unstable(feature = "async_iter_from_iter", issue = "81798")] +impl AsyncIterator for FromIter { type Item = I::Item; fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { diff --git a/library/core/src/stream/mod.rs b/library/core/src/async_iter/mod.rs similarity index 56% rename from library/core/src/stream/mod.rs rename to library/core/src/async_iter/mod.rs index b59a46d5f3a96..0c6f637711b37 100644 --- a/library/core/src/stream/mod.rs +++ b/library/core/src/async_iter/mod.rs @@ -1,10 +1,9 @@ //! Composable asynchronous iteration. //! -//! If futures are asynchronous values, then streams are asynchronous -//! iterators. If you've found yourself with an asynchronous collection of some kind, +//! If you've found yourself with an asynchronous collection of some kind, //! and needed to perform an operation on the elements of said collection, -//! you'll quickly run into 'streams'. Streams are heavily used in idiomatic -//! asynchronous Rust code, so it's worth becoming familiar with them. +//! you'll quickly run into 'async iterators'. Async Iterators are heavily used in +//! idiomatic asynchronous Rust code, so it's worth becoming familiar with them. //! //! Before explaining more, let's talk about how this module is structured: //! @@ -12,71 +11,71 @@ //! //! This module is largely organized by type: //! -//! * [Traits] are the core portion: these traits define what kind of streams +//! * [Traits] are the core portion: these traits define what kind of async iterators //! exist and what you can do with them. The methods of these traits are worth //! putting some extra study time into. -//! * Functions provide some helpful ways to create some basic streams. +//! * Functions provide some helpful ways to create some basic async iterators. //! * Structs are often the return types of the various methods on this //! module's traits. You'll usually want to look at the method that creates //! the `struct`, rather than the `struct` itself. For more detail about why, -//! see '[Implementing Stream](#implementing-stream)'. +//! see '[Implementing Async Iterator](#implementing-async-iterator)'. //! //! [Traits]: #traits //! -//! That's it! Let's dig into streams. +//! That's it! Let's dig into async iterators. //! -//! # Stream +//! # Async Iterators //! -//! The heart and soul of this module is the [`Stream`] trait. The core of -//! [`Stream`] looks like this: +//! The heart and soul of this module is the [`AsyncIterator`] trait. The core of +//! [`AsyncIterator`] looks like this: //! //! ``` //! # use core::task::{Context, Poll}; //! # use core::pin::Pin; -//! trait Stream { +//! trait AsyncIterator { //! type Item; //! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; //! } //! ``` //! -//! Unlike `Iterator`, `Stream` makes a distinction between the [`poll_next`] -//! method which is used when implementing a `Stream`, and a (to-be-implemented) -//! `next` method which is used when consuming a stream. Consumers of `Stream` +//! Unlike `Iterator`, `AsyncIterator` makes a distinction between the [`poll_next`] +//! method which is used when implementing an `AsyncIterator`, and a (to-be-implemented) +//! `next` method which is used when consuming an async iterator. Consumers of `AsyncIterator` //! only need to consider `next`, which when called, returns a future which -//! yields `Option`. +//! yields `Option`. //! //! The future returned by `next` will yield `Some(Item)` as long as there are //! elements, and once they've all been exhausted, will yield `None` to indicate //! that iteration is finished. If we're waiting on something asynchronous to -//! resolve, the future will wait until the stream is ready to yield again. +//! resolve, the future will wait until the async iterator is ready to yield again. //! -//! Individual streams may choose to resume iteration, and so calling `next` +//! Individual async iterators may choose to resume iteration, and so calling `next` //! again may or may not eventually yield `Some(Item)` again at some point. //! -//! [`Stream`]'s full definition includes a number of other methods as well, +//! [`AsyncIterator`]'s full definition includes a number of other methods as well, //! but they are default methods, built on top of [`poll_next`], and so you get //! them for free. //! //! [`Poll`]: super::task::Poll -//! [`poll_next`]: Stream::poll_next +//! [`poll_next`]: AsyncIterator::poll_next //! -//! # Implementing Stream +//! # Implementing Async Iterator //! -//! Creating a stream of your own involves two steps: creating a `struct` to -//! hold the stream's state, and then implementing [`Stream`] for that +//! Creating an async iterator of your own involves two steps: creating a `struct` to +//! hold the async iterator's state, and then implementing [`AsyncIterator`] for that //! `struct`. //! -//! Let's make a stream named `Counter` which counts from `1` to `5`: +//! Let's make an async iterator named `Counter` which counts from `1` to `5`: //! //! ```no_run -//! #![feature(async_stream)] -//! # use core::stream::Stream; +//! #![feature(async_iterator)] +//! # use core::async_iter::AsyncIterator; //! # use core::task::{Context, Poll}; //! # use core::pin::Pin; //! //! // First, the struct: //! -//! /// A stream which counts from one to five +//! /// An async iterator which counts from one to five //! struct Counter { //! count: usize, //! } @@ -90,9 +89,9 @@ //! } //! } //! -//! // Then, we implement `Stream` for our `Counter`: +//! // Then, we implement `AsyncIterator` for our `Counter`: //! -//! impl Stream for Counter { +//! impl AsyncIterator for Counter { //! // we will be counting with usize //! type Item = usize; //! @@ -113,17 +112,17 @@ //! //! # Laziness //! -//! Streams are *lazy*. This means that just creating a stream doesn't _do_ a -//! whole lot. Nothing really happens until you call `poll_next`. This is -//! sometimes a source of confusion when creating a stream solely for its side +//! Async iterators are *lazy*. This means that just creating an async iterator doesn't +//! _do_ a whole lot. Nothing really happens until you call `poll_next`. This is +//! sometimes a source of confusion when creating an async iterator solely for its side //! effects. The compiler will warn us about this kind of behavior: //! //! ```text -//! warning: unused result that must be used: streams do nothing unless polled +//! warning: unused result that must be used: async iterators do nothing unless polled //! ``` +mod async_iter; mod from_iter; -mod stream; +pub use async_iter::AsyncIterator; pub use from_iter::{from_iter, FromIter}; -pub use stream::Stream; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e52d52e954c8f..66f2d2ec1e931 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -304,6 +304,8 @@ pub mod ops; pub mod any; pub mod array; pub mod ascii; +#[unstable(feature = "async_iterator", issue = "79024")] +pub mod async_iter; pub mod cell; pub mod char; pub mod ffi; @@ -315,8 +317,6 @@ pub mod panic; pub mod panicking; pub mod pin; pub mod result; -#[unstable(feature = "async_stream", issue = "79024")] -pub mod stream; pub mod sync; pub mod fmt; diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 092b7cf0f2cd5..95be879e319aa 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -1,10 +1,10 @@ +use crate::async_iter::AsyncIterator; use crate::cell::UnsafeCell; use crate::fmt; use crate::future::Future; use crate::ops::{Deref, DerefMut}; use crate::pin::Pin; use crate::ptr::{NonNull, Unique}; -use crate::stream::Stream; use crate::task::{Context, Poll}; /// A marker trait which represents "panic safe" types in Rust. @@ -290,8 +290,8 @@ impl Future for AssertUnwindSafe { } } -#[unstable(feature = "async_stream", issue = "79024")] -impl Stream for AssertUnwindSafe { +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for AssertUnwindSafe { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 4f44a3183a6ec..f3bb2eeb8586e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -232,7 +232,7 @@ #![feature(array_error_internals)] #![feature(assert_matches)] #![feature(associated_type_bounds)] -#![feature(async_stream)] +#![feature(async_iterator)] #![feature(atomic_mut_ptr)] #![feature(auto_traits)] #![feature(bench_black_box)] @@ -403,6 +403,8 @@ pub use alloc_crate::vec; pub use core::any; #[stable(feature = "core_array", since = "1.36.0")] pub use core::array; +#[unstable(feature = "async_iterator", issue = "79024")] +pub use core::async_iter; #[stable(feature = "rust1", since = "1.0.0")] pub use core::cell; #[stable(feature = "rust1", since = "1.0.0")] @@ -457,8 +459,6 @@ pub use core::pin; pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use core::result; -#[unstable(feature = "async_stream", issue = "79024")] -pub use core::stream; #[stable(feature = "i128", since = "1.26.0")] #[allow(deprecated, deprecated_in_future)] pub use core::u128; From b80057d08d9f1b1726ec99dc57296cffec246bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 3 Feb 2022 23:12:25 +0100 Subject: [PATCH 6/7] compiler: clippy::complexity fixes useless_format map_flatten useless_conversion needless_bool filter_next clone_on_copy needless_option_as_deref --- compiler/rustc_ast/src/attr/mod.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_middle/src/middle/stability.rs | 2 +- compiler/rustc_middle/src/ty/relate.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- .../rustc_mir_transform/src/coverage/query.rs | 3 +-- .../src/partitioning/mod.rs | 22 +++++++++---------- .../rustc_parse/src/parser/diagnostics.rs | 8 +++---- compiler/rustc_parse/src/parser/generics.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 7 +++--- .../rustc_resolve/src/late/diagnostics.rs | 2 +- .../src/traits/error_reporting/mod.rs | 3 +-- .../src/traits/project.rs | 2 +- compiler/rustc_typeck/src/astconv/errors.rs | 3 +-- compiler/rustc_typeck/src/check/check.rs | 2 +- compiler/rustc_typeck/src/check/demand.rs | 6 ++--- .../check/generator_interior/drop_ranges.rs | 2 +- .../drop_ranges/cfg_build.rs | 4 ++-- compiler/rustc_typeck/src/collect/type_of.rs | 2 +- 22 files changed, 39 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 6a0ace04d4b61..b94b8c8721693 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -230,7 +230,7 @@ impl AttrItem { } pub fn meta_kind(&self) -> Option { - Some(MetaItemKind::from_mac_args(&self.args)?) + MetaItemKind::from_mac_args(&self.args) } } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a6ecfa4520608..e01f232a61028 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -775,7 +775,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { ); let mut all_stable = true; for ident in - attr.meta_item_list().into_iter().flatten().map(|nested| nested.ident()).flatten() + attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) { let name = ident.name; let stable_since = lang_features diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 8672459b5da3a..34403bdffa3d9 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -278,7 +278,7 @@ pub unsafe fn create_module<'ll>( "sign-return-address-all\0".as_ptr().cast(), pac_opts.leaf.into(), ); - let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true }; + let is_bkey: bool = pac_opts.key != PAuthKey::A; llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Error, diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index c21d19a62279f..6976999c0e4f7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -476,7 +476,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::Subslice { from, to, from_end } => { let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from as u64)); let projected_ty = - PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, elem.clone()).ty; + PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, *elem).ty; subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty)); if subslice.layout.is_unsized() { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8065911afb9da..f71fb58cf6b9f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1039,7 +1039,7 @@ fn check_matcher_core( )); err.span_suggestion( span, - &format!("try a `pat_param` fragment specifier instead"), + "try a `pat_param` fragment specifier instead", suggestion, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 6d531d3e7d620..d080405927bd6 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -198,7 +198,7 @@ fn deprecation_message( } else { let since = since.as_ref().map(Symbol::as_str); - if since.as_deref() == Some("TBD") { + if since == Some("TBD") { format!("use of {} `{}` that will be deprecated in a future Rust version", kind, path) } else { format!( diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index bb040acd2703d..e5d44a7242169 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -855,7 +855,7 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { Ok(ty::ProjectionPredicate { projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, - term: relation.relate(a.term, b.term)?.into(), + term: relation.relate(a.term, b.term)?, }) } } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 9e32c0162e617..0e9ece77da7e1 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -214,7 +214,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_impls(self, def_id: DefId) -> impl Iterator + 'tcx { let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id); - blanket_impls.iter().chain(non_blanket_impls.iter().map(|(_, v)| v).flatten()).cloned() + blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned() } } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 46de6d939a1df..da921904523c4 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -140,7 +140,7 @@ fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx Cod let body = mir_body(tcx, def_id); body.basic_blocks() .iter() - .map(|data| { + .flat_map(|data| { data.statements.iter().filter_map(|statement| match statement.kind { StatementKind::Coverage(box ref coverage) => { if is_inlined(body, statement) { @@ -152,7 +152,6 @@ fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx Cod _ => None, }) }) - .flatten() .collect() } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 67597a0d7b46b..b8684a09fd7ce 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -220,18 +220,16 @@ pub fn partition<'tcx>( let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect(); cgus.sort_by_key(|cgu| cgu.size_estimate()); - let dead_code_cgu = if let Some(cgu) = cgus - .into_iter() - .rev() - .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) - .next() - { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut post_inlining.codegen_units[0] - }; + let dead_code_cgu = + if let Some(cgu) = cgus.into_iter().rev().find(|cgu| { + cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External) + }) { + cgu + } else { + // If there are no CGUs that have externally linked items, + // then we just pick the first CGU as a fallback. + &mut post_inlining.codegen_units[0] + }; dead_code_cgu.make_code_coverage_dead_code_cgu(); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7b74b137d21ae..def23005fbe11 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2156,7 +2156,7 @@ impl<'a> Parser<'a> { | PatKind::TupleStruct(qself @ None, path, _) | PatKind::Path(qself @ None, path) => match &first_pat.kind { PatKind::Ident(_, ident, _) => { - path.segments.insert(0, PathSegment::from_ident(ident.clone())); + path.segments.insert(0, PathSegment::from_ident(*ident)); path.span = new_span; show_sugg = true; first_pat = pat; @@ -2183,8 +2183,8 @@ impl<'a> Parser<'a> { Path { span: new_span, segments: vec![ - PathSegment::from_ident(old_ident.clone()), - PathSegment::from_ident(ident.clone()), + PathSegment::from_ident(*old_ident), + PathSegment::from_ident(*ident), ], tokens: None, }, @@ -2194,7 +2194,7 @@ impl<'a> Parser<'a> { } PatKind::Path(old_qself, old_path) => { let mut segments = old_path.segments.clone(); - segments.push(PathSegment::from_ident(ident.clone())); + segments.push(PathSegment::from_ident(*ident)); let path = PatKind::Path( old_qself.clone(), Path { span: new_span, segments, tokens: None }, diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 62ed104aef37c..4b57aa1f24a1c 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -260,7 +260,7 @@ impl<'a> Parser<'a> { let ate_comma = self.eat(&token::Comma); if self.eat_keyword_noexpect(kw::Where) { - let msg = &format!("cannot define duplicate `where` clauses on an item"); + let msg = "cannot define duplicate `where` clauses on an item"; let mut err = self.struct_span_err(self.token.span, msg); err.span_label(lo, "previous `where` clause starts here"); err.span_suggestion_verbose( diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c7edcb077b917..acce66760fdb9 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1362,8 +1362,7 @@ impl<'a> Resolver<'a> { .filter(|(_, module)| { current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module) }) - .map(|(_, module)| module.kind.name()) - .flatten(), + .flat_map(|(_, module)| module.kind.name()), ) .filter(|c| !c.to_string().is_empty()) .collect::>(); @@ -1859,7 +1858,7 @@ crate fn show_candidates( let instead = if instead { " instead" } else { "" }; let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); - for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() { + for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { err.note(note); } @@ -1942,7 +1941,7 @@ crate fn show_candidates( multi_span.push_span_label(span, format!("`{}`: not accessible", name)); } - for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() { + for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { err.note(note); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d05f139e3bf5a..e4db645e0827c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1167,7 +1167,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestion( span, &"use this syntax instead", - format!("{path_str}"), + path_str.to_string(), Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6cb19416cd769..6f282e297a775 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1432,8 +1432,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { self.tcx .associated_items(did) .in_definition_order() - .filter(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) - .next() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) }, ) }) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5e7d4c8b415c3..2b5172c4544d2 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -957,7 +957,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); } obligations.extend(result.obligations); - Ok(Some(result.value.into())) + Ok(Some(result.value)) } Ok(Projected::NoProgress(projected_ty)) => { let result = Normalized { value: projected_ty, obligations: vec![] }; diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index a49d6e24f2621..7e9abe3a250db 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -211,8 +211,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let all_candidate_names: Vec<_> = all_candidates() - .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) - .flatten() + .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) .filter_map( |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None }, ) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 18a0a8767d45b..07facf61fc428 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -387,7 +387,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b .multipart_suggestion_verbose( "wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped", vec![ - (ty_span.shrink_to_lo(), format!("std::mem::ManuallyDrop<")), + (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()), (ty_span.shrink_to_hi(), ">".into()), ], Applicability::MaybeIncorrect, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 2409346298da9..8ddd00dfc8e92 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -340,7 +340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{}: ", ident), - None => format!(""), + None => String::new(), }; match &compatible_variants[..] { @@ -683,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{}: ", ident), - None => format!(""), + None => String::new(), }; if let Some(hir::Node::Expr(hir::Expr { @@ -875,7 +875,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{}: ", ident), - None => format!(""), + None => String::new(), }; let (span, suggestion) = if self.is_else_if_block(expr) { // Don't suggest nonsense like `else *if` diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs index 4b8f01e3535bd..8d3f7d11d937f 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs @@ -242,7 +242,7 @@ impl DropRangesBuilder { fn add_control_edge(&mut self, from: PostOrderId, to: PostOrderId) { trace!("adding control edge from {:?} to {:?}", from, to); - self.node_mut(from.into()).successors.push(to.into()); + self.node_mut(from).successors.push(to); } } diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs index d7d52ab823cee..1b1a561fabc8c 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs @@ -444,7 +444,7 @@ impl DropRangesBuilder { fn drop_at(&mut self, value: TrackedValue, location: PostOrderId) { let value = self.tracked_value_index(value); - self.node_mut(location.into()).drops.push(value); + self.node_mut(location).drops.push(value); } fn reinit_at(&mut self, value: TrackedValue, location: PostOrderId) { @@ -454,7 +454,7 @@ impl DropRangesBuilder { // ignore this. None => return, }; - self.node_mut(location.into()).reinits.push(value); + self.node_mut(location).reinits.push(value); } /// Looks up PostOrderId for any control edges added by HirId and adds a proper edge for them. diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 5cb0d309ff4ee..f827fa653b6b1 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -526,7 +526,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( DUMMY_SP, - &format!("Could not find associated const on trait"), + "Could not find associated const on trait", ) } } From 3d19c8defd776eb7e9e113cf49c3e1d2f51e408e Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sat, 8 Jan 2022 23:30:19 -0500 Subject: [PATCH 7/7] Suggest copying trait associated type bounds on lifetime error --- .../error_reporting/nice_region_error/mod.rs | 2 +- .../src/infer/error_reporting/note.rs | 52 +++++++++++++++++++ compiler/rustc_infer/src/infer/mod.rs | 17 ++++++ compiler/rustc_middle/src/traits/mod.rs | 6 +++ .../src/traits/error_reporting/suggestions.rs | 3 +- .../rustc_typeck/src/check/compare_method.rs | 9 +++- .../impl_bounds.stderr | 7 ++- .../generic-associated-types/issue-88595.rs | 5 +- .../issue-88595.stderr | 22 +------- .../issue-90014.stderr | 7 ++- .../generic-associated-types/issue-92033.rs | 39 ++++++++++++++ .../issue-92033.stderr | 22 ++++++++ 12 files changed, 163 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-92033.rs create mode 100644 src/test/ui/generic-associated-types/issue-92033.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 8512597cb9137..f44e6e04346b2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -64,7 +64,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { .or_else(|| self.try_report_mismatched_static_lifetime()) } - pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { + pub(super) fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { match (&self.error, self.regions) { (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)), (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 8e5efa12ac6c1..8671ecba6e924 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -102,6 +102,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...so that the definition in impl matches the definition from the trait", ); } + infer::CheckAssociatedTypeBounds { ref parent, .. } => { + self.note_region_origin(err, &parent); + } } } @@ -345,6 +348,55 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_item_def_id, &format!("`{}: {}`", sup, sub), ), + infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { + let mut err = self.report_concrete_failure(*parent, sub, sup); + + let trait_item_span = self.tcx.def_span(trait_item_def_id); + let item_name = self.tcx.item_name(impl_item_def_id); + err.span_label( + trait_item_span, + format!("definition of `{}` from trait", item_name), + ); + + let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); + let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); + + let impl_predicates: rustc_data_structures::stable_set::FxHashSet<_> = + impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); + let clauses: Vec<_> = trait_predicates + .predicates + .into_iter() + .filter(|&(pred, _)| !impl_predicates.contains(pred)) + .map(|(pred, _)| format!("{}", pred)) + .collect(); + + if !clauses.is_empty() { + let where_clause_span = self + .tcx + .hir() + .get_generics(impl_item_def_id.expect_local()) + .unwrap() + .where_clause + .tail_span_for_suggestion(); + + let suggestion = format!( + "{} {}", + if !impl_predicates.is_empty() { "," } else { " where" }, + clauses.join(", "), + ); + err.span_suggestion( + where_clause_span, + &format!( + "try copying {} from the trait", + if clauses.len() > 1 { "these clauses" } else { "this clause" } + ), + suggestion, + rustc_errors::Applicability::MaybeIncorrect, + ); + } + + err + } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f0a4ec813134c..57ac98ca897ee 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -438,6 +438,13 @@ pub enum SubregionOrigin<'tcx> { /// Comparing the signature and requirements of an impl associated type /// against the containing trait CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId }, + + /// Checking that the bounds of a trait's associated type hold for a given impl + CheckAssociatedTypeBounds { + parent: Box>, + impl_item_def_id: DefId, + trait_item_def_id: DefId, + }, } // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -1832,6 +1839,7 @@ impl<'tcx> SubregionOrigin<'tcx> { ReferenceOutlivesReferent(_, a) => a, CompareImplMethodObligation { span, .. } => span, CompareImplTypeObligation { span, .. } => span, + CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), } } @@ -1862,6 +1870,15 @@ impl<'tcx> SubregionOrigin<'tcx> { trait_item_def_id, }, + traits::ObligationCauseCode::CheckAssociatedTypeBounds { + impl_item_def_id, + trait_item_def_id, + } => SubregionOrigin::CheckAssociatedTypeBounds { + impl_item_def_id, + trait_item_def_id, + parent: Box::new(default()), + }, + _ => default(), } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 1123cab807651..b54418e520171 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -285,6 +285,12 @@ pub enum ObligationCauseCode<'tcx> { trait_item_def_id: DefId, }, + /// Checking that the bounds of a trait's associated type hold for a given impl + CheckAssociatedTypeBounds { + impl_item_def_id: DefId, + trait_item_def_id: DefId, + }, + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 40cb9647a3555..6068b90aef82c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1932,7 +1932,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::AwaitableExpr(_) | ObligationCauseCode::ForLoopIterator | ObligationCauseCode::QuestionMark - | ObligationCauseCode::LetElse => {} + | ObligationCauseCode::LetElse + | ObligationCauseCode::CheckAssociatedTypeBounds { .. } => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 457e9cf1ea54a..38449c2a76a5b 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1378,7 +1378,14 @@ pub fn check_type_bounds<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); - let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); + let normalize_cause = ObligationCause::new( + impl_ty_span, + impl_ty_hir_id, + ObligationCauseCode::CheckAssociatedTypeBounds { + impl_item_def_id: impl_ty.def_id, + trait_item_def_id: trait_ty.def_id, + }, + ); let mk_cause = |span: Span| { let code = if span.is_dummy() { traits::MiscObligation diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 5be431f2933b3..bd0dea372194d 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -19,8 +19,13 @@ LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:35 | +LL | type B<'a, 'b> where 'a: 'b; + | ---------------------------- definition of `B` from trait +... LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); - | ^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^ + | | + | help: try copying this clause from the trait: `, 'a: 'b` | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/impl_bounds.rs:17:12 diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs index e397390783f66..c97d17811ba7c 100644 --- a/src/test/ui/generic-associated-types/issue-88595.rs +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -8,7 +8,7 @@ trait A<'a> { // FIXME(generic_associated_types): Remove one of the below bounds // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085 where - 'a: 'b, Self: 'a, Self: 'b; + Self: 'a, Self: 'b; fn a(&'a self) -> Self::B<'a>; } @@ -17,8 +17,7 @@ struct C; impl<'a> A<'a> for C { type B<'b> = impl Clone; - //~^ ERROR: lifetime bound not satisfied - //~| ERROR: could not find defining uses + //~^ ERROR: could not find defining uses fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope } diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr index cb462871ccd32..4e4f86bbac87c 100644 --- a/src/test/ui/generic-associated-types/issue-88595.stderr +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -1,22 +1,5 @@ -error[E0478]: lifetime bound not satisfied - --> $DIR/issue-88595.rs:19:18 - | -LL | type B<'b> = impl Clone; - | ^^^^^^^^^^ - | -note: lifetime parameter instantiated with the lifetime `'a` as defined here - --> $DIR/issue-88595.rs:18:6 - | -LL | impl<'a> A<'a> for C { - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined here - --> $DIR/issue-88595.rs:19:12 - | -LL | type B<'b> = impl Clone; - | ^^ - error: non-defining opaque type use in defining scope - --> $DIR/issue-88595.rs:23:23 + --> $DIR/issue-88595.rs:22:23 | LL | fn a(&'a self) -> Self::B<'a> {} | ^^^^^^^^^^^ @@ -35,6 +18,5 @@ error: could not find defining uses LL | type B<'b> = impl Clone; | ^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 23e8d08af3428..f8fb71bbddb4b 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -1,8 +1,13 @@ error[E0477]: the type `&mut ()` does not fulfill the required lifetime --> $DIR/issue-90014.rs:14:20 | +LL | type Fut<'a> where Self: 'a; + | ---------------------------- definition of `Fut` from trait +... LL | type Fut<'a> = impl Future; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try copying this clause from the trait: `where Self: 'a` | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:14:14 diff --git a/src/test/ui/generic-associated-types/issue-92033.rs b/src/test/ui/generic-associated-types/issue-92033.rs new file mode 100644 index 0000000000000..1d5f7d5c0099e --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92033.rs @@ -0,0 +1,39 @@ +#![feature(generic_associated_types)] + +struct Texture; + +trait Surface { + type TextureIter<'a>: Iterator + where + Self: 'a; + + fn get_texture(&self) -> Self::TextureIter<'_>; +} + +trait Swapchain { + type Surface<'a>: Surface + where + Self: 'a; + + fn get_surface(&self) -> Self::Surface<'_>; +} + +impl<'s> Surface for &'s Texture { + type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + //~^ ERROR the type + + fn get_texture(&self) -> Self::TextureIter<'_> { + let option: Option<&Texture> = Some(self); + option.into_iter() + } +} + +impl Swapchain for Texture { + type Surface<'a> = &'a Texture; + + fn get_surface(&self) -> Self::Surface<'_> { + self + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr new file mode 100644 index 0000000000000..caa6618f39884 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -0,0 +1,22 @@ +error[E0477]: the type `&'s Texture` does not fulfill the required lifetime + --> $DIR/issue-92033.rs:22:28 + | +LL | / type TextureIter<'a>: Iterator +LL | | where +LL | | Self: 'a; + | |_________________- definition of `TextureIter` from trait +... +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try copying this clause from the trait: `where Self: 'a` + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-92033.rs:22:22 + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`.