From 0b5963023d9d3bdbbf27e9f92171047cf2a7f008 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 15 Jan 2022 15:43:02 +0100 Subject: 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 (limited to 'src') 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 cc3b257a5c5..00000000000 --- 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 ae166b17840..00000000000 --- 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 783d826a53d..69a286f0b74 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 3f1a70458e3..f328e4d9d04 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() {} -- cgit 1.4.1-3-g733a5 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: 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 (limited to 'src') diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index c08b141b557..97cb7aa0dde 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 8f6745246fd..00000000000 --- 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 253fec5e578..00000000000 --- 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 0667364d13c..00000000000 --- 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 98190b060ce..00000000000 --- 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 00000000000..b2f681c01d1 --- /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 00000000000..dd693cf316d --- /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 + -- cgit 1.4.1-3-g733a5 From b651d5a1f4b3b8ab54926d4f5dd0390a94f5bac3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Jan 2022 20:38:38 -0800 Subject: Fix Inline MIR pass on a function with un-satisfiable bounds --- compiler/rustc_mir_transform/src/inline.rs | 13 +++++++++++-- compiler/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 (limited to 'src') diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e1f30fef44f..6220daa0b6b 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 848aba7c912..a0c60898c15 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 00000000000..1b010566cbc --- /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 00000000000..10f80f8de0c --- /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`. -- cgit 1.4.1-3-g733a5 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: Suggest copying trait associated type bounds on lifetime error --- .../infer/error_reporting/nice_region_error/mod.rs | 2 +- .../rustc_infer/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 +- compiler/rustc_typeck/src/check/compare_method.rs | 9 +++- .../ui/generic-associated-types/impl_bounds.stderr | 7 ++- .../ui/generic-associated-types/issue-88595.rs | 5 +-- .../ui/generic-associated-types/issue-88595.stderr | 22 +-------- .../ui/generic-associated-types/issue-90014.stderr | 7 ++- .../ui/generic-associated-types/issue-92033.rs | 39 ++++++++++++++++ .../ui/generic-associated-types/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 (limited to 'src') 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 8512597cb91..f44e6e04346 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 8e5efa12ac6..8671ecba6e9 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 f0a4ec81313..57ac98ca897 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 1123cab8076..b54418e5201 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 40cb9647a35..6068b90aef8 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 457e9cf1ea5..38449c2a76a 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 5be431f2933..bd0dea37219 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 e397390783f..c97d17811ba 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 cb462871ccd..4e4f86bbac8 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 23e8d08af34..f8fb71bbddb 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 00000000000..1d5f7d5c009 --- /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 00000000000..caa6618f398 --- /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`. -- cgit 1.4.1-3-g733a5