From 6100b74fbcf8da2122bd5ee4a9361965d8bf3429 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 29 Jun 2020 11:14:31 -0700 Subject: [PATCH 01/22] Advertise correct stable version for const control flow --- src/librustc_feature/accepted.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs index d93c17b05b498..d16f023c00a62 100644 --- a/src/librustc_feature/accepted.rs +++ b/src/librustc_feature/accepted.rs @@ -262,9 +262,9 @@ declare_features! ( /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254), None), /// Allows the use of `if` and `match` in constants. - (accepted, const_if_match, "1.45.0", Some(49146), None), + (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows the use of `loop` and `while` in constants. - (accepted, const_loop, "1.45.0", Some(52000), None), + (accepted, const_loop, "1.46.0", Some(52000), None), /// Allows `#[track_caller]` to be used which provides /// accurate caller location reporting during panic (RFC 2091). (accepted, track_caller, "1.46.0", Some(47809), None), From 4fb260bb32a2da7d7ea63b759eef77072a95614b Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 4 Jul 2020 18:41:30 +0100 Subject: [PATCH 02/22] Guard against non-monomorphized type_id intrinsic call --- src/librustc_mir/interpret/intrinsics.rs | 12 +++++++++-- src/test/ui/consts/issue-73976.rs | 26 ++++++++++++++++++++++++ src/test/ui/consts/issue-73976.stderr | 14 +++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/issue-73976.rs create mode 100644 src/test/ui/consts/issue-73976.stderr diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 5836fc9c95a80..29549041d258c 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size}; @@ -54,6 +54,9 @@ crate fn eval_nullary_intrinsic<'tcx>( let name = tcx.item_name(def_id); Ok(match name { sym::type_name => { + if tp_ty.needs_subst() { + throw_inval!(TooGeneric); + } let alloc = type_name::alloc_type_name(tcx, tp_ty); ConstValue::Slice { data: alloc, start: 0, end: alloc.len() } } @@ -68,7 +71,12 @@ crate fn eval_nullary_intrinsic<'tcx>( }; ConstValue::from_machine_usize(n, &tcx) } - sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty)), + sym::type_id => { + if tp_ty.needs_subst() { + throw_inval!(TooGeneric); + } + ConstValue::from_u64(tcx.type_id_hash(tp_ty)) + } sym::variant_count => { if let ty::Adt(ref adt, _) = tp_ty.kind { ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx) diff --git a/src/test/ui/consts/issue-73976.rs b/src/test/ui/consts/issue-73976.rs new file mode 100644 index 0000000000000..ef141791c2cc8 --- /dev/null +++ b/src/test/ui/consts/issue-73976.rs @@ -0,0 +1,26 @@ +// This test is from #73976. We previously did not check if a type is monomorphized +// before calculating its type id, which leads to the bizzare behaviour below that +// TypeId of a generic type does not match itself. +// +// This test case should either run-pass or be rejected at compile time. +// Currently we just disallow this usage and require pattern is monomorphic. + +#![feature(const_type_id)] + +use std::any::TypeId; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} + +fn main() { + assert!(check_type_id::()); +} diff --git a/src/test/ui/consts/issue-73976.stderr b/src/test/ui/consts/issue-73976.stderr new file mode 100644 index 0000000000000..dbb7690b849c8 --- /dev/null +++ b/src/test/ui/consts/issue-73976.stderr @@ -0,0 +1,14 @@ +error: could not evaluate constant pattern + --> $DIR/issue-73976.rs:19:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976.rs:19:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 4c69d4bc05f43d801390c8498eea6e317e9d4b12 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 11 Jul 2020 14:50:03 -0400 Subject: [PATCH 03/22] Add the aarch64-apple-darwin target This is a basic copy-paste-modify from the existing x86_64-apple-darwin target. --- .../spec/aarch64_apple_darwin.rs | 30 +++++++++++++++++++ src/librustc_target/spec/mod.rs | 1 + .../spec/x86_64_apple_darwin.rs | 5 +++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/librustc_target/spec/aarch64_apple_darwin.rs diff --git a/src/librustc_target/spec/aarch64_apple_darwin.rs b/src/librustc_target/spec/aarch64_apple_darwin.rs new file mode 100644 index 0000000000000..60daf10b36afe --- /dev/null +++ b/src/librustc_target/spec/aarch64_apple_darwin.rs @@ -0,0 +1,30 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::apple_base::opts(); + base.cpu = "apple-a12".to_string(); + base.max_atomic_width = Some(128); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); + + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); + + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "aarch64"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + + Ok(Target { + llvm_target, + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), + arch: arch.to_string(), + target_os: "macos".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base }, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d53033ba3ba20..5a97ef441c203 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -574,6 +574,7 @@ supported_targets! { ("i686-unknown-haiku", i686_unknown_haiku), ("x86_64-unknown-haiku", x86_64_unknown_haiku), + ("aarch64-apple-darwin", aarch64_apple_darwin), ("x86_64-apple-darwin", x86_64_apple_darwin), ("i686-apple-darwin", i686_apple_darwin), diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index 31011e8474958..909aebec70b58 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -5,7 +5,10 @@ pub fn target() -> TargetResult { base.cpu = "core2".to_string(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.eliminate_frame_pointer = false; - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.pre_link_args.insert( + LinkerFlavor::Gcc, + vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()], + ); base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; From 804241ea06f20acc9bfd83c229507e726609f927 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 11 Jul 2020 14:52:30 -0400 Subject: [PATCH 04/22] Update dependencies that have knowledge about aarch64-apple-darwin --- Cargo.lock | 8 ++++---- src/librustc_llvm/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34a33eca3f40b..8391cba278631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,9 +412,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fde55d2a2bfaa4c9668bbc63f531fbdeee3ffe188f4662511ce2c22b3eedebe" +checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" dependencies = [ "jobserver", ] @@ -1576,9 +1576,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9" dependencies = [ "rustc-std-workspace-core", ] diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 4fc02e348f646..1a034294cd8eb 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -14,8 +14,8 @@ static-libstdcpp = [] emscripten = [] [dependencies] -libc = "0.2" +libc = "0.2.73" [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0.1" +cc = "1.0.58" From b3340b5cea5fdaefa4cbc7eec8ceb0592ebe2255 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 21 Jul 2020 02:28:51 +0100 Subject: [PATCH 05/22] Expand test to cover type_name and monomorphic use --- src/test/ui/consts/issue-73976-monomorphic.rs | 36 +++++++++++++++++++ ...ue-73976.rs => issue-73976-polymorphic.rs} | 16 ++++++++- .../ui/consts/issue-73976-polymorphic.stderr | 26 ++++++++++++++ src/test/ui/consts/issue-73976.stderr | 14 -------- 4 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/consts/issue-73976-monomorphic.rs rename src/test/ui/consts/{issue-73976.rs => issue-73976-polymorphic.rs} (62%) create mode 100644 src/test/ui/consts/issue-73976-polymorphic.stderr delete mode 100644 src/test/ui/consts/issue-73976.stderr diff --git a/src/test/ui/consts/issue-73976-monomorphic.rs b/src/test/ui/consts/issue-73976-monomorphic.rs new file mode 100644 index 0000000000000..7706a97f23b48 --- /dev/null +++ b/src/test/ui/consts/issue-73976-monomorphic.rs @@ -0,0 +1,36 @@ +// check-pass +// +// This test is complement to the test in issue-73976-polymorphic.rs. +// In that test we ensure that polymorphic use of type_id and type_name in patterns +// will be properly rejected. This test will ensure that monomorphic use of these +// would not be wrongly rejected in patterns. + +#![feature(const_type_id)] +#![feature(const_type_name)] + +use std::any::{self, TypeId}; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) +} + +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) +} + +fn main() { + assert!(check_type_id::()); + assert!(check_type_name_len::()); +} diff --git a/src/test/ui/consts/issue-73976.rs b/src/test/ui/consts/issue-73976-polymorphic.rs similarity index 62% rename from src/test/ui/consts/issue-73976.rs rename to src/test/ui/consts/issue-73976-polymorphic.rs index ef141791c2cc8..28b84518719a1 100644 --- a/src/test/ui/consts/issue-73976.rs +++ b/src/test/ui/consts/issue-73976-polymorphic.rs @@ -6,8 +6,9 @@ // Currently we just disallow this usage and require pattern is monomorphic. #![feature(const_type_id)] +#![feature(const_type_name)] -use std::any::TypeId; +use std::any::{self, TypeId}; pub struct GetTypeId(T); @@ -21,6 +22,19 @@ const fn check_type_id() -> bool { //~| ERROR could not evaluate constant pattern } +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} + fn main() { assert!(check_type_id::()); + assert!(check_type_name_len::()); } diff --git a/src/test/ui/consts/issue-73976-polymorphic.stderr b/src/test/ui/consts/issue-73976-polymorphic.stderr new file mode 100644 index 0000000000000..c90ce2bd06a67 --- /dev/null +++ b/src/test/ui/consts/issue-73976-polymorphic.stderr @@ -0,0 +1,26 @@ +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/consts/issue-73976.stderr b/src/test/ui/consts/issue-73976.stderr deleted file mode 100644 index dbb7690b849c8..0000000000000 --- a/src/test/ui/consts/issue-73976.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: could not evaluate constant pattern - --> $DIR/issue-73976.rs:19:37 - | -LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/issue-73976.rs:19:37 - | -LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - From 430bd39a0da2b17e5c7ca4842e25b7f523c51522 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 22 Jul 2020 14:42:45 +0900 Subject: [PATCH 06/22] Do not ICE on assoc type with bad placeholder --- src/librustc_typeck/collect.rs | 8 +++++++- .../ui/typeck/typeck_type_placeholder_item.rs | 2 ++ .../typeck/typeck_type_placeholder_item.stderr | 18 ++++++++++++------ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c3b54f1461426..cb9348a9521bc 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -730,7 +730,13 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { placeholder_type_error(tcx, None, &[], visitor.0, false); } - hir::TraitItemKind::Type(_, None) => {} + hir::TraitItemKind::Type(_, None) => { + // #74612: Visit and try to find bad placeholders + // even if there is no concrete type. + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_trait_item(trait_item); + placeholder_type_error(tcx, None, &[], visitor.0, false); + } }; tcx.ensure().predicates_of(def_id); diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 133c5231031fd..2c8b1e76b1b82 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -194,6 +194,8 @@ trait Qux { const D: _ = 42; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures // type E: _; // FIXME: make the parser propagate the existence of `B` + type F: std::ops::Fn(_); + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures } impl Qux for Struct { type A = _; diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index a1945f2b9cf4e..782ff4948cda4 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:203:5 + --> $DIR/typeck_type_placeholder_item.rs:205:5 | LL | const C: _; | ^^^^^^^^^^- @@ -545,6 +545,12 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace `_` with the correct type: `i32` +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:197:26 + | +LL | type F: std::ops::Fn(_); + | ^ not allowed in type signatures + error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:40:24 | @@ -582,25 +588,25 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace with the correct return type: `main::FnTest9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:199:14 + --> $DIR/typeck_type_placeholder_item.rs:201:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:201:14 + --> $DIR/typeck_type_placeholder_item.rs:203:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:203:14 + --> $DIR/typeck_type_placeholder_item.rs:205:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:206:14 + --> $DIR/typeck_type_placeholder_item.rs:208:14 | LL | const D: _ = 42; | ^ @@ -608,7 +614,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace `_` with the correct type: `i32` -error: aborting due to 66 previous errors +error: aborting due to 67 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From 747bc8ec88b94ddfbd665d21bb87732411bcd1f7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 21 Jul 2020 14:53:39 -0400 Subject: [PATCH 07/22] Enable perf try builder This adds a dedicated branch for perf to use for CI, intended to allow perf to enqueue builds without needing to use bors. bors is great, but bors requires an open PR to work, and we want to invoke perf on closed PRs sometimes (in particular, rollups). --- .github/workflows/ci.yml | 7 ++++--- src/ci/github-actions/ci.yml | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e0808c0d5896..d83971b70bedc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ name: CI branches: - auto - try + - try-perf - master pull_request: branches: @@ -146,7 +147,7 @@ jobs: CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" strategy: matrix: include: @@ -717,7 +718,7 @@ jobs: try-success: needs: - try - if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a success run: exit 0 @@ -727,7 +728,7 @@ jobs: try-failure: needs: - try - if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a failure run: exit 1 diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 425e34f1af624..0aeb6a04e5f77 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -247,6 +247,7 @@ on: branches: - auto - try + - try-perf - master pull_request: branches: @@ -285,7 +286,7 @@ jobs: name: try env: <<: [*shared-ci-variables, *prod-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust' + if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust' strategy: matrix: include: @@ -645,11 +646,11 @@ jobs: # successful listening to webhooks only. try-success: needs: [try] - if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" <<: *base-success-job try-failure: needs: [try] - if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" <<: *base-failure-job auto-success: needs: [auto] From 49b9a6486ab0814f4c7d57c22c75216fdc1ebf14 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Jul 2020 15:49:04 +0300 Subject: [PATCH 08/22] rustc_target: Add a target spec option for disabling `--eh-frame-hdr` --- src/librustc_codegen_ssa/back/link.rs | 4 +++- src/librustc_codegen_ssa/back/linker.rs | 8 +------- src/librustc_target/spec/apple_base.rs | 1 + src/librustc_target/spec/freestanding_base.rs | 1 + src/librustc_target/spec/illumos_base.rs | 1 + src/librustc_target/spec/mod.rs | 8 ++++++++ src/librustc_target/spec/msp430_none_elf.rs | 2 ++ src/librustc_target/spec/riscv32i_unknown_none_elf.rs | 1 + src/librustc_target/spec/riscv32imac_unknown_none_elf.rs | 1 + src/librustc_target/spec/riscv32imc_unknown_none_elf.rs | 1 + src/librustc_target/spec/riscv64gc_unknown_none_elf.rs | 1 + src/librustc_target/spec/riscv64imac_unknown_none_elf.rs | 1 + src/librustc_target/spec/solaris_base.rs | 1 + src/librustc_target/spec/windows_gnu_base.rs | 1 + 14 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 2d65282ce7798..b53b82a1e62fc 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1598,7 +1598,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( } // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER - cmd.add_eh_frame_header(); + if sess.target.target.options.eh_frame_header { + cmd.add_eh_frame_header(); + } // NO-OPT-OUT, OBJECT-FILES-NO if crt_objects_fallback { diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index e64aafa599fd8..d1ae9e372695f 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -619,13 +619,7 @@ impl<'a> Linker for GccLinker<'a> { // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't, // so we just always add it. fn add_eh_frame_header(&mut self) { - if !self.sess.target.target.options.is_like_osx - && !self.sess.target.target.options.is_like_windows - && !self.sess.target.target.options.is_like_solaris - && self.sess.target.target.target_os != "uefi" - { - self.linker_arg("--eh-frame-hdr"); - } + self.linker_arg("--eh-frame-hdr"); } } diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index bdd5a893d34e2..e7b565ae9cad9 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -31,6 +31,7 @@ pub fn opts() -> TargetOptions { has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, + eh_frame_header: false, // This environment variable is pretty magical but is intended for // producing deterministic builds. This was first discovered to be used diff --git a/src/librustc_target/spec/freestanding_base.rs b/src/librustc_target/spec/freestanding_base.rs index 5402ea074fae1..c338856228dc6 100644 --- a/src/librustc_target/spec/freestanding_base.rs +++ b/src/librustc_target/spec/freestanding_base.rs @@ -25,6 +25,7 @@ pub fn opts() -> TargetOptions { has_rpath: false, pre_link_args: args, position_independent_executables: false, + eh_frame_header: false, ..Default::default() } } diff --git a/src/librustc_target/spec/illumos_base.rs b/src/librustc_target/spec/illumos_base.rs index 35ac346fb3f6f..214142b88fc2c 100644 --- a/src/librustc_target/spec/illumos_base.rs +++ b/src/librustc_target/spec/illumos_base.rs @@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions { is_like_solaris: true, limit_rdylib_exports: false, // Linker doesn't support this eliminate_frame_pointer: false, + eh_frame_header: false, late_link_args, // While we support ELF TLS, rust requires a way to register diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d53033ba3ba20..61dba6c72bd4f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -987,6 +987,11 @@ pub struct TargetOptions { /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults /// to false (uses .init_array). pub use_ctors_section: bool, + + /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header + /// used to locate unwinding information is passed + /// (only has effect if the linker is `ld`-like). + pub eh_frame_header: bool, } impl Default for TargetOptions { @@ -1078,6 +1083,7 @@ impl Default for TargetOptions { relax_elf_relocations: false, llvm_args: vec![], use_ctors_section: false, + eh_frame_header: true, } } } @@ -1470,6 +1476,7 @@ impl Target { key!(relax_elf_relocations, bool); key!(llvm_args, list); key!(use_ctors_section, bool); + key!(eh_frame_header, bool); // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -1707,6 +1714,7 @@ impl ToJson for Target { target_option_val!(relax_elf_relocations); target_option_val!(llvm_args); target_option_val!(use_ctors_section); + target_option_val!(eh_frame_header); if default.unsupported_abis != self.options.unsupported_abis { d.insert( diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs index c6d0308f8f82f..f75697996ac78 100644 --- a/src/librustc_target/spec/msp430_none_elf.rs +++ b/src/librustc_target/spec/msp430_none_elf.rs @@ -56,6 +56,8 @@ pub fn target() -> TargetResult { // See the thumb_base.rs file for an explanation of this value emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() }, }) diff --git a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs index 977aa896f2520..5b5e342000b55 100644 --- a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs @@ -25,6 +25,7 @@ pub fn target() -> TargetResult { relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, unsupported_abis: super::riscv_base::unsupported_abis(), + eh_frame_header: false, ..Default::default() }, }) diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs index 1a85cdff1315c..4cef5c42d8ddf 100644 --- a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs @@ -25,6 +25,7 @@ pub fn target() -> TargetResult { relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, unsupported_abis: super::riscv_base::unsupported_abis(), + eh_frame_header: false, ..Default::default() }, }) diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs index e3c1c6908a23a..8ad563e441de3 100644 --- a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs @@ -25,6 +25,7 @@ pub fn target() -> TargetResult { relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, unsupported_abis: super::riscv_base::unsupported_abis(), + eh_frame_header: false, ..Default::default() }, }) diff --git a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs index 857af4ceb0d9f..3aeb3f3ca72b2 100644 --- a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs @@ -26,6 +26,7 @@ pub fn target() -> TargetResult { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, unsupported_abis: super::riscv_base::unsupported_abis(), + eh_frame_header: false, ..Default::default() }, }) diff --git a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs index 36fe7730f95bf..d8144964dc913 100644 --- a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs +++ b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs @@ -26,6 +26,7 @@ pub fn target() -> TargetResult { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, unsupported_abis: super::riscv_base::unsupported_abis(), + eh_frame_header: false, ..Default::default() }, }) diff --git a/src/librustc_target/spec/solaris_base.rs b/src/librustc_target/spec/solaris_base.rs index 8d3a3563f4164..3d7f0034b8b10 100644 --- a/src/librustc_target/spec/solaris_base.rs +++ b/src/librustc_target/spec/solaris_base.rs @@ -8,6 +8,7 @@ pub fn opts() -> TargetOptions { target_family: Some("unix".to_string()), is_like_solaris: true, limit_rdylib_exports: false, // Linker doesn't support this + eh_frame_header: false, ..Default::default() } diff --git a/src/librustc_target/spec/windows_gnu_base.rs b/src/librustc_target/spec/windows_gnu_base.rs index 680dbbad4b0a0..69236e98e58d7 100644 --- a/src/librustc_target/spec/windows_gnu_base.rs +++ b/src/librustc_target/spec/windows_gnu_base.rs @@ -91,6 +91,7 @@ pub fn opts() -> TargetOptions { abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, + eh_frame_header: false, ..Default::default() } From 4b052024a05d529e2c51cf40a525340f20310466 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Jul 2020 18:44:15 +0300 Subject: [PATCH 09/22] build: Remove unnecessary `cargo:rerun-if-env-changed` annotations --- src/librustc_ast/build.rs | 5 ----- src/librustc_attr/build.rs | 5 ----- src/librustc_codegen_llvm/build.rs | 6 ------ src/librustc_codegen_ssa/build.rs | 4 ---- src/librustc_driver/build.rs | 7 ------- src/librustc_incremental/build.rs | 4 ---- src/librustc_interface/build.rs | 4 ---- src/librustc_llvm/build.rs | 2 +- src/librustc_metadata/build.rs | 5 ----- src/librustc_middle/build.rs | 12 ------------ src/librustc_session/session.rs | 2 +- src/librustc_target/build.rs | 4 ---- 12 files changed, 2 insertions(+), 58 deletions(-) delete mode 100644 src/librustc_ast/build.rs delete mode 100644 src/librustc_attr/build.rs delete mode 100644 src/librustc_codegen_llvm/build.rs delete mode 100644 src/librustc_codegen_ssa/build.rs delete mode 100644 src/librustc_driver/build.rs delete mode 100644 src/librustc_incremental/build.rs delete mode 100644 src/librustc_interface/build.rs delete mode 100644 src/librustc_metadata/build.rs delete mode 100644 src/librustc_middle/build.rs delete mode 100644 src/librustc_target/build.rs diff --git a/src/librustc_ast/build.rs b/src/librustc_ast/build.rs deleted file mode 100644 index 9b861f9640904..0000000000000 --- a/src/librustc_ast/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL"); - println!("cargo:rerun-if-env-changed=CFG_DISABLE_UNSTABLE_FEATURES"); -} diff --git a/src/librustc_attr/build.rs b/src/librustc_attr/build.rs deleted file mode 100644 index 863f2b7337b25..0000000000000 --- a/src/librustc_attr/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL"); -} diff --git a/src/librustc_codegen_llvm/build.rs b/src/librustc_codegen_llvm/build.rs deleted file mode 100644 index d1fc624c68927..0000000000000 --- a/src/librustc_codegen_llvm/build.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_VERSION"); - println!("cargo:rerun-if-env-changed=CFG_PREFIX"); - println!("cargo:rerun-if-env-changed=CFG_LLVM_ROOT"); -} diff --git a/src/librustc_codegen_ssa/build.rs b/src/librustc_codegen_ssa/build.rs deleted file mode 100644 index ea2af6e192e7c..0000000000000 --- a/src/librustc_codegen_ssa/build.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL"); -} diff --git a/src/librustc_driver/build.rs b/src/librustc_driver/build.rs deleted file mode 100644 index 414d13445f01e..0000000000000 --- a/src/librustc_driver/build.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_RELEASE"); - println!("cargo:rerun-if-env-changed=CFG_VERSION"); - println!("cargo:rerun-if-env-changed=CFG_VER_DATE"); - println!("cargo:rerun-if-env-changed=CFG_VER_HASH"); -} diff --git a/src/librustc_incremental/build.rs b/src/librustc_incremental/build.rs deleted file mode 100644 index d230ba91039ad..0000000000000 --- a/src/librustc_incremental/build.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_VERSION"); -} diff --git a/src/librustc_interface/build.rs b/src/librustc_interface/build.rs deleted file mode 100644 index 79a343e0fee0b..0000000000000 --- a/src/librustc_interface/build.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=RUSTC_INSTALL_BINDIR"); -} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 78e27b10ec657..f00bd7d47f035 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -163,7 +163,7 @@ fn main() { cfg.define(&flag, None); } - println!("cargo:rerun-if-changed-env=LLVM_RUSTLLVM"); + println!("cargo:rerun-if-env-changed=LLVM_RUSTLLVM"); if env::var_os("LLVM_RUSTLLVM").is_some() { cfg.define("LLVM_RUSTLLVM", None); } diff --git a/src/librustc_metadata/build.rs b/src/librustc_metadata/build.rs deleted file mode 100644 index 7d5c58ecea2a1..0000000000000 --- a/src/librustc_metadata/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_VERSION"); - println!("cargo:rerun-if-env-changed=CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"); -} diff --git a/src/librustc_middle/build.rs b/src/librustc_middle/build.rs deleted file mode 100644 index af7723aea34e4..0000000000000 --- a/src/librustc_middle/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -use std::env; - -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_LIBDIR_RELATIVE"); - println!("cargo:rerun-if-env-changed=CFG_COMPILER_HOST_TRIPLE"); - println!("cargo:rerun-if-env-changed=RUSTC_VERIFY_LLVM_IR"); - - if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() { - println!("cargo:rustc-cfg=always_verify_llvm_ir"); - } -} diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 4ad95e95e9a86..1b8f6cdd8bebc 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -548,7 +548,7 @@ impl Session { self.opts.debugging_opts.asm_comments } pub fn verify_llvm_ir(&self) -> bool { - self.opts.debugging_opts.verify_llvm_ir || cfg!(always_verify_llvm_ir) + self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some() } pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats diff --git a/src/librustc_target/build.rs b/src/librustc_target/build.rs deleted file mode 100644 index 368200b776d74..0000000000000 --- a/src/librustc_target/build.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CFG_DEFAULT_LINKER"); -} From 0b662c23580420c3d6a9e457df54c17a934ebdc9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Jul 2020 19:13:02 +0300 Subject: [PATCH 10/22] build: Remove unnecessary `build = "build.rs"` annotations --- src/libprofiler_builtins/Cargo.toml | 1 - src/librustc_attr/Cargo.toml | 1 - src/librustc_llvm/Cargo.toml | 1 - src/libstd/Cargo.toml | 1 - src/libunwind/Cargo.toml | 1 - src/tools/error_index_generator/Cargo.toml | 1 - 6 files changed, 6 deletions(-) diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml index 0d36bd0b39d76..899f923b957fe 100644 --- a/src/libprofiler_builtins/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -1,6 +1,5 @@ [package] authors = ["The Rust Project Developers"] -build = "build.rs" name = "profiler_builtins" version = "0.0.0" edition = "2018" diff --git a/src/librustc_attr/Cargo.toml b/src/librustc_attr/Cargo.toml index 677796a8df0b3..496becb8f1b59 100644 --- a/src/librustc_attr/Cargo.toml +++ b/src/librustc_attr/Cargo.toml @@ -3,7 +3,6 @@ authors = ["The Rust Project Developers"] name = "rustc_attr" version = "0.0.0" edition = "2018" -build = "build.rs" [lib] name = "rustc_attr" diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 4fc02e348f646..ccc417c166429 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -2,7 +2,6 @@ authors = ["The Rust Project Developers"] name = "rustc_llvm" version = "0.0.0" -build = "build.rs" edition = "2018" [lib] diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 42403bdb1bcea..f5d8119f711cb 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -2,7 +2,6 @@ authors = ["The Rust Project Developers"] name = "std" version = "0.0.0" -build = "build.rs" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust.git" description = "The Rust Standard Library" diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index 77bcfffd506c9..b6baa9a8c6bcc 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -2,7 +2,6 @@ authors = ["The Rust Project Developers"] name = "unwind" version = "0.0.0" -build = "build.rs" edition = "2018" include = [ '/libunwind/*', diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index 992af261b8352..787e08404e1c6 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -3,7 +3,6 @@ authors = ["The Rust Project Developers"] name = "error_index_generator" version = "0.0.0" edition = "2018" -build = "build.rs" [dependencies] rustdoc = { path = "../../librustdoc" } From 461c5764577414d0232508177f8099a27b96b303 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Jul 2020 19:51:19 +0300 Subject: [PATCH 11/22] build: Harden env var tracking in build scripts --- src/build_helper/lib.rs | 16 ++++++++++++---- src/librustc_llvm/build.rs | 24 ++++++++++-------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 43c3c5773ce5b..e30da8d56e10f 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,3 +1,5 @@ +use std::ffi::{OsStr, OsString}; +use std::fmt::Display; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -28,6 +30,14 @@ macro_rules! t { }; } +/// Reads an environment variable and adds it to dependencies. +/// Supposed to be used for all variables except those set for build scripts by cargo +/// https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts +pub fn tracked_env_var_os + Display>(key: K) -> Option { + println!("cargo:rerun-if-env-changed={}", key); + env::var_os(key) +} + // Because Cargo adds the compiler's dylib path to our library search path, llvm-config may // break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM // shared library, which means that when our freshly built llvm-config goes to load it's @@ -37,10 +47,8 @@ macro_rules! t { // perfect -- we might actually want to see something from Cargo's added library paths -- but // for now it works. pub fn restore_library_path() { - println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH_VAR"); - println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH"); - let key = env::var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR"); - if let Some(env) = env::var_os("REAL_LIBRARY_PATH") { + let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR"); + if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") { env::set_var(&key, &env); } else { env::remove_var(&key); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index f00bd7d47f035..21b8080714c17 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -2,12 +2,12 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::output; +use build_helper::{output, tracked_env_var_os}; fn detect_llvm_link() -> (&'static str, &'static str) { // Force the link mode we want, preferring static by default, but // possibly overridden by `configure --enable-llvm-link-shared`. - if env::var_os("LLVM_LINK_SHARED").is_some() { + if tracked_env_var_os("LLVM_LINK_SHARED").is_some() { ("dylib", "--link-shared") } else { ("static", "--link-static") @@ -15,8 +15,7 @@ fn detect_llvm_link() -> (&'static str, &'static str) { } fn main() { - println!("cargo:rerun-if-env-changed=RUST_CHECK"); - if env::var_os("RUST_CHECK").is_some() { + if tracked_env_var_os("RUST_CHECK").is_some() { // If we're just running `check`, there's no need for LLVM to be built. return; } @@ -25,8 +24,8 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let llvm_config = - env::var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| { - if let Some(dir) = env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + tracked_env_var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| { + if let Some(dir) = tracked_env_var_os("CARGO_TARGET_DIR").map(PathBuf::from) { let to_test = dir .parent() .unwrap() @@ -46,8 +45,6 @@ fn main() { } let llvm_config = llvm_config.unwrap_or_else(|| PathBuf::from("llvm-config")); - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); - // Test whether we're cross-compiling LLVM. This is a pretty rare case // currently where we're producing an LLVM for a different platform than // what this build script is currently running on. @@ -163,12 +160,11 @@ fn main() { cfg.define(&flag, None); } - println!("cargo:rerun-if-env-changed=LLVM_RUSTLLVM"); - if env::var_os("LLVM_RUSTLLVM").is_some() { + if tracked_env_var_os("LLVM_RUSTLLVM").is_some() { cfg.define("LLVM_RUSTLLVM", None); } - if env::var_os("LLVM_NDEBUG").is_some() { + if tracked_env_var_os("LLVM_NDEBUG").is_some() { cfg.define("NDEBUG", None); cfg.debug(false); } @@ -255,7 +251,7 @@ fn main() { // librustc_llvm, for example when using static libc++, we may need to // manually specify the library search path and -ldl -lpthread as link // dependencies. - let llvm_linker_flags = env::var_os("LLVM_LINKER_FLAGS"); + let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS"); if let Some(s) = llvm_linker_flags { for lib in s.into_string().unwrap().split_whitespace() { if lib.starts_with("-l") { @@ -266,8 +262,8 @@ fn main() { } } - let llvm_static_stdcpp = env::var_os("LLVM_STATIC_STDCPP"); - let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX"); + let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP"); + let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX"); let stdcppname = if target.contains("openbsd") { if target.contains("sparc64") { "estdc++" } else { "c++" } From 7be36a86f7b7798e662d844b33bd744a136b4f60 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Jul 2020 20:06:37 +0300 Subject: [PATCH 12/22] build: Avoid unnecessary build script reruns in libstd Add a FIXME to build scripts in profiler_builtins --- src/libprofiler_builtins/build.rs | 2 ++ src/libstd/build.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index bb7d59e113c08..d2cb873058c28 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -9,6 +9,8 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let cfg = &mut cc::Build::new(); + // FIXME: `rerun-if-changed` directives are not currently emitted and the build script + // will not rerun on changes in these source files or headers included into them. let mut profile_sources = vec![ "GCDAProfiling.c", "InstrProfiling.c", diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 58fb6fda19aab..83073cc77dd1a 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -1,6 +1,7 @@ use std::env; fn main() { + println!("cargo:rerun-if-changed=build.rs"); let target = env::var("TARGET").expect("TARGET was not set"); if target.contains("linux") { if target.contains("android") { From 6513148c146c36b0d1649cdb65a3a4737599252f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jun 2020 18:52:00 -0700 Subject: [PATCH 13/22] Detect when `'static` obligation might come from an `impl` Address #71341. --- .../nice_region_error/static_impl_trait.rs | 465 ++++++++++-------- .../cache/project-fn-ret-contravariant.rs | 2 +- ...ject-fn-ret-contravariant.transmute.stderr | 23 +- .../cache/project-fn-ret-invariant.rs | 2 +- .../project-fn-ret-invariant.transmute.stderr | 28 +- .../dyn-trait.stderr | 25 +- .../constant-in-expr-inherent-1.stderr | 25 +- .../ui/regions/regions-addr-of-self.stderr | 28 +- ...mplicit-static-bound-without-suggestion.rs | 14 + ...cit-static-bound-without-suggestion.stderr | 18 + ...dyn-trait-with-implicit-static-bound.fixed | 37 ++ ...on-dyn-trait-with-implicit-static-bound.rs | 37 ++ ...yn-trait-with-implicit-static-bound.stderr | 29 ++ 13 files changed, 431 insertions(+), 302 deletions(-) create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index b6e971feb0e5f..da776f269d510 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -2,227 +2,302 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use rustc_errors::{struct_span_err, Applicability, ErrorReported}; -use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; -use rustc_middle::ty::RegionKind; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::{ + GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef, + TyKind, +}; +use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); - if let Some(RegionResolutionError::SubSupConflict( - _, - var_origin, - ref sub_origin, - sub_r, - ref sup_origin, - sup_r, - )) = self.error - { - debug!( - "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", - var_origin, sub_origin, sub_r, sup_origin, sup_r - ); - let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); - let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id); - if fn_returns.is_empty() { - return None; + let tcx = self.tcx(); + let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? { + RegionResolutionError::SubSupConflict( + _, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ) if **sub_r == RegionKind::ReStatic => { + (var_origin, sub_origin, sub_r, sup_origin, sup_r) } - debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); - if *sub_r == RegionKind::ReStatic { - let sp = var_origin.span(); - let return_sp = sub_origin.span(); - let param_info = self.find_param_with_region(sup_r, sub_r)?; - let (lifetime_name, lifetime) = if sup_r.has_name() { - (sup_r.to_string(), format!("lifetime `{}`", sup_r)) - } else { - ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) - }; - let mut err = struct_span_err!( - self.tcx().sess, - sp, - E0759, - "cannot infer an appropriate lifetime" - ); - err.span_label( - param_info.param_ty_span, - &format!("this data with {}...", lifetime), - ); - debug!("try_report_static_impl_trait: param_info={:?}", param_info); + _ => return None, + }; + debug!( + "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", + var_origin, sub_origin, sub_r, sup_origin, sup_r + ); + let anon_reg_sup = tcx.is_suitable_region(sup_r)?; + debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); + let sp = var_origin.span(); + let return_sp = sub_origin.span(); + let param = self.find_param_with_region(sup_r, sub_r)?; + let (lifetime_name, lifetime) = if sup_r.has_name() { + (sup_r.to_string(), format!("lifetime `{}`", sup_r)) + } else { + ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) + }; + let mut err = struct_span_err!(tcx.sess, sp, E0759, "cannot infer an appropriate lifetime"); + err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + debug!("try_report_static_impl_trait: param_info={:?}", param); - // We try to make the output have fewer overlapping spans if possible. - if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) - && sup_origin.span() != return_sp - { - // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` + // We try to make the output have fewer overlapping spans if possible. + if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) + && sup_origin.span() != return_sp + { + // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` - // Customize the spans and labels depending on their relative order so - // that split sentences flow correctly. - if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { - // Avoid the following: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ---------^- - // - // and instead show: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ - err.span_label( - sup_origin.span(), - "...is captured here, requiring it to live as long as `'static`", - ); - } else { - err.span_label(sup_origin.span(), "...is captured here..."); - if return_sp < sup_origin.span() { - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", - ); - } else { - err.span_label( - return_sp, - "...and is required to live as long as `'static` here", - ); - } - } + // Customize the spans and labels depending on their relative order so + // that split sentences flow correctly. + if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { + // Avoid the following: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ---------^- + // + // and instead show: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ^ + err.span_label( + sup_origin.span(), + "...is captured here, requiring it to live as long as `'static`", + ); + } else { + err.span_label(sup_origin.span(), "...is captured here..."); + if return_sp < sup_origin.span() { + err.span_note( + return_sp, + "...and is required to live as long as `'static` here", + ); } else { err.span_label( return_sp, - "...is captured and required to live as long as `'static` here", + "...and is required to live as long as `'static` here", ); } + } + } else { + err.span_label( + return_sp, + "...is captured and required to live as long as `'static` here", + ); + } - // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; - let arg = match param_info.param.pat.simple_ident() { - Some(simple_ident) => format!("argument `{}`", simple_ident), - None => "the argument".to_string(), - }; - let explicit = - format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = - format!("explicit `'static` bound to the lifetime of {}", arg); - let captures = format!("captures data from {}", arg); - let add_static_bound = - "alternatively, add an explicit `'static` bound to this reference"; - let plus_lt = format!(" + {}", lifetime_name); - for fn_return in fn_returns { - if fn_return.span.desugaring_kind().is_some() { - // Skip `async` desugaring `impl Future`. - continue; - } - match fn_return.kind { - TyKind::OpaqueDef(item_id, _) => { - let item = self.tcx().hir().item(item_id.id); - let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { - opaque - } else { - err.emit(); - return Some(ErrorReported); - }; + self.find_impl_on_dyn_trait(&mut err, param.param_ty); - if let Some(span) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { - name: LifetimeName::Static, - span, - .. - }) => Some(*span), - _ => None, - }) - .next() - { - err.span_suggestion_verbose( - span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), - lifetime_name.clone(), - Applicability::MaybeIncorrect, - ); - err.span_suggestion_verbose( - param_info.param_ty_span, - add_static_bound, - param_info.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } else if let Some(_) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { name, span, .. }) - if name.ident().to_string() == lifetime_name => - { - Some(*span) - } - _ => None, - }) - .next() + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); + debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + let consider = "consider changing the"; + let declare = "to declare that the"; + let arg = match param.param.pat.simple_ident() { + Some(simple_ident) => format!("argument `{}`", simple_ident), + None => "the argument".to_string(), + }; + let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = format!("explicit `'static` bound to the lifetime of {}", arg); + let captures = format!("captures data from {}", arg); + let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); + for fn_return in fn_returns { + if fn_return.span.desugaring_kind().is_some() { + // Skip `async` desugaring `impl Future`. + continue; + } + match fn_return.kind { + TyKind::OpaqueDef(item_id, _) => { + let item = tcx.hir().item(item_id.id); + let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { + opaque + } else { + err.emit(); + return Some(ErrorReported); + }; + + if let Some(span) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some(*span), + _ => None, + }) + .next() + { + err.span_suggestion_verbose( + span, + &format!("{} `impl Trait`'s {}", consider, explicit_static), + lifetime_name.clone(), + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param.param_ty_span, + add_static_bound, + param.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } else if let Some(_) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { name, span, .. }) + if name.ident().to_string() == lifetime_name => { - } else { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), - Applicability::MaybeIncorrect, - ); + Some(*span) } - } - TyKind::TraitObject(_, lt) => match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} trait object {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), - Applicability::MaybeIncorrect, - ); - } - name if name.ident().to_string() != lifetime_name => { - // With this check we avoid suggesting redundant bounds. This - // would happen if there are nested impl/dyn traits and only - // one of them has the bound we'd suggest already there, like - // in `impl Foo + '_`. - err.span_suggestion_verbose( - lt.span, - &format!("{} trait object's {}", consider, explicit_static), - lifetime_name.clone(), - Applicability::MaybeIncorrect, - ); + _ => None, + }) + .next() + { + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); + } + } + TyKind::TraitObject(_, lt) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); + } + name if name.ident().to_string() != lifetime_name => { + // With this check we avoid suggesting redundant bounds. This + // would happen if there are nested impl/dyn traits and only + // one of them has the bound we'd suggest already there, like + // in `impl Foo + '_`. + err.span_suggestion_verbose( + lt.span, + &format!("{} trait object's {}", consider, explicit_static), + lifetime_name.clone(), + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param.param_ty_span, + add_static_bound, + param.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + _ => {} + }, + _ => {} + } + } + err.emit(); + Some(ErrorReported) + } + + /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default + /// `'static` obligation. Find `impl` blocks that are implemented + fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool { + let tcx = self.tcx(); + + // Find the trait object types in the argument. + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + debug!("TraitObjectVisitor {:?}", v.0); + + // Find all the `impl`s in the local scope that can be called on the type parameter. + // FIXME: this doesn't find `impl dyn Trait { /**/ }`. + let impl_self_tys = tcx + .all_traits(LOCAL_CRATE) + .iter() + .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did)) + .filter_map(|impl_node| { + let impl_did = tcx.hir().local_def_id(*impl_node); + if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = + tcx.hir().get_if_local(impl_did.to_def_id()) + { + Some(self_ty) + } else { + None + } + }); + let mut suggested = false; + for self_ty in impl_self_tys { + if let TyKind::TraitObject( + poly_trait_refs, + Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) = self_ty.kind + { + for p in poly_trait_refs { + if let PolyTraitRef { + trait_ref: + TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. }, + .. + } = p + { + for found_did in &v.0 { + if did == found_did { + // We've found an `impl Foo for dyn Bar {}`. + // FIXME: we should change this so it also works for + // `impl Foo for Box {}`. err.span_suggestion_verbose( - param_info.param_ty_span, - add_static_bound, - param_info.param_ty.to_string(), + self_ty.span.shrink_to_hi(), + "this `impl` introduces an implicit `'static` requirement, \ + consider changing it", + " + '_".to_string(), Applicability::MaybeIncorrect, ); + suggested = true; } - _ => {} - }, - _ => {} + } } } err.emit(); return Some(ErrorReported); } } - None + suggested + } +} + +/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. +struct TraitObjectVisitor(Vec); + +impl TypeVisitor<'_> for TraitObjectVisitor { + fn visit_ty(&mut self, t: Ty<'_>) -> bool { + match t.kind { + ty::Dynamic(preds, RegionKind::ReStatic) => { + if let Some(def_id) = preds.principal_def_id() { + self.0.push(def_id); + } + false + } + _ => t.super_visit_with(self), + } } } diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs index 8c6073e2f7a49..1eeb01ccc846e 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs @@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { #[cfg(transmute)] // one instantiations: BAD fn baz<'a,'b>(x: &'a u32) -> &'static u32 { - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0759 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 5ea98dcd4a972..36812d3c0441e 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -1,26 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0759]: cannot infer an appropriate lifetime --> $DIR/project-fn-ret-contravariant.rs:38:8 | -LL | bar(foo, x) - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8... - --> $DIR/project-fn-ret-contravariant.rs:37:8 - | LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { - | ^^ -note: ...so that reference does not outlive borrowed content - --> $DIR/project-fn-ret-contravariant.rs:38:13 - | -LL | bar(foo, x) - | ^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/project-fn-ret-contravariant.rs:38:4 - | + | ------- this data with lifetime `'a`... LL | bar(foo, x) - | ^^^^^^^^^^^ + | ----^^^---- ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 0034d796826de..08d864f7836d2 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { // Cannot instantiate `foo` with any lifetime other than `'a`, // since it is provided as input. - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0759 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index ef57f9e0bc480..9cec0780b3ca8 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,30 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0759]: cannot infer an appropriate lifetime --> $DIR/project-fn-ret-invariant.rs:49:9 | -LL | bar(foo, x) - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8... - --> $DIR/project-fn-ret-invariant.rs:45:8 - | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { - | ^^ -note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:49:14 - | -LL | bar(foo, x) - | ^ - = note: expected `Type<'_>` - found `Type<'a>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:49:5 - | + | -------- this data with lifetime `'a`... +... LL | bar(foo, x) - | ^^^^^^^^^^^ - = note: expected `Type<'static>` - found `Type<'_>` + | ----^^^---- ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index 268008c211129..397cb3750c266 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -1,30 +1,17 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0759]: cannot infer an appropriate lifetime --> $DIR/dyn-trait.rs:20:16 | -LL | static_val(x); - | ^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26... - --> $DIR/dyn-trait.rs:19:26 - | LL | fn with_dyn_debug_static<'a>(x: Box) { - | ^^ -note: ...so that the expression is assignable - --> $DIR/dyn-trait.rs:20:16 - | + | ------------------- this data with lifetime `'a`... LL | static_val(x); - | ^ - = note: expected `std::boxed::Box` - found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the types are compatible + | ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here --> $DIR/dyn-trait.rs:20:5 | LL | static_val(x); | ^^^^^^^^^^ - = note: expected `StaticTrait` - found `StaticTrait` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index 8421dc1d0c130..f823f69c76f67 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -1,28 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0759]: cannot infer an appropriate lifetime --> $DIR/constant-in-expr-inherent-1.rs:8:5 | -LL | >::C - | ^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8... - --> $DIR/constant-in-expr-inherent-1.rs:7:8 - | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { - | ^^ -note: ...so that the types are compatible - --> $DIR/constant-in-expr-inherent-1.rs:8:5 - | -LL | >::C - | ^^^^^^^^^^^^ - = note: expected `Foo<'_>` - found `Foo<'a>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/constant-in-expr-inherent-1.rs:8:5 - | + | ------- this data with lifetime `'a`... LL | >::C - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr index a0b8b6b51e5a1..c15a933379c85 100644 --- a/src/test/ui/regions/regions-addr-of-self.stderr +++ b/src/test/ui/regions/regions-addr-of-self.stderr @@ -1,29 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error[E0759]: cannot infer an appropriate lifetime --> $DIR/regions-addr-of-self.rs:7:37 | +LL | pub fn chase_cat(&mut self) { + | --------- this data with an anonymous lifetime `'_`... LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5... - --> $DIR/regions-addr-of-self.rs:6:5 - | -LL | / pub fn chase_cat(&mut self) { -LL | | let p: &'static mut usize = &mut self.cats_chased; -LL | | *p += 1; -LL | | } - | |_____^ -note: ...so that reference does not outlive borrowed content - --> $DIR/regions-addr-of-self.rs:7:37 - | -LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that reference does not outlive borrowed content - --> $DIR/regions-addr-of-self.rs:7:37 - | -LL | let p: &'static mut usize = &mut self.cats_chased; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs new file mode 100644 index 0000000000000..dd53ee06ff5ee --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs @@ -0,0 +1,14 @@ +trait OtherTrait<'a> {} +impl<'a> OtherTrait<'a> for &'a () {} + +trait ObjectTrait {} + +impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } +} + +fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr new file mode 100644 index 0000000000000..4618b540c70ee --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9 + | +LL | val.use_self() + | ^^^^^^^^ lifetime mismatch + | + = note: expected reference `&(dyn ObjectTrait + 'static)` + found reference `&(dyn ObjectTrait + 'a)` +note: the lifetime `'a` as defined on the function body at 10:11... + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed new file mode 100644 index 0000000000000..dfe475d3c0694 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -0,0 +1,37 @@ +// run-rustfix +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs new file mode 100644 index 0000000000000..85e6c2993b9b1 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -0,0 +1,37 @@ +// run-rustfix +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr new file mode 100644 index 0000000000000..6780459adbeac --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -0,0 +1,29 @@ +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0759`. From 4e08bab87dbddea55247013bab9735fa2148ec84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Jun 2020 15:26:12 -0700 Subject: [PATCH 14/22] Increase accuracy of lifetime bound on trait object impl suggestion --- src/librustc_hir/hir.rs | 12 +- src/librustc_infer/infer/combine.rs | 10 +- .../infer/error_reporting/mod.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 184 +++++++++++++----- .../error_reporting/nice_region_error/util.rs | 14 +- src/librustc_infer/infer/mod.rs | 18 +- src/librustc_infer/lib.rs | 1 + src/librustc_middle/traits/mod.rs | 2 + .../traits/structural_impls.rs | 1 + src/librustc_middle/ty/mod.rs | 8 +- .../traits/error_reporting/suggestions.rs | 1 + src/librustc_typeck/check/method/confirm.rs | 24 ++- ...mplicit-static-bound-without-suggestion.rs | 14 -- ...cit-static-bound-without-suggestion.stderr | 18 -- ...dyn-trait-with-implicit-static-bound.fixed | 36 ++++ ...rait-with-implicit-static-bound.nll.stderr | 22 +++ ...on-dyn-trait-with-implicit-static-bound.rs | 36 ++++ ...yn-trait-with-implicit-static-bound.stderr | 32 ++- 18 files changed, 321 insertions(+), 114 deletions(-) delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index f56522406b0a7..6474dc318d329 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2198,7 +2198,17 @@ pub enum IsAsync { NotAsync, } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +#[derive( + Copy, + Clone, + PartialEq, + RustcEncodable, + RustcDecodable, + Debug, + HashStable_Generic, + Eq, + Hash +)] pub enum Defaultness { Default { has_value: bool }, Final, diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 3b564e03d9a94..c63464e5baec9 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations}; use rustc_ast::ast; use rustc_hir::def_id::DefId; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { }; debug!("generalize: for_universe = {:?}", for_universe); + debug!("generalize: trace = {:?}", self.trace); let mut generalize = Generalizer { infcx: self.infcx, - span: self.trace.cause.span, + cause: &self.trace.cause, for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), for_universe, ambient_variance, @@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, /// The span, used when creating new type variables and things. - span: Span, + cause: &'cx ObligationCause<'tcx>, /// The vid of the type variable that is in the process of being /// instantiated; if we find this within the type we are folding, @@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) + Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe)) } fn consts( diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 633589db2704c..ff905faa95a9f 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), infer::AddrOfRegion(_) => " for borrow expression".to_string(), - infer::Autoref(_) => " for autoref".to_string(), + infer::Autoref(_, _) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::LateBoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index da776f269d510..0aa1d65612ee6 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -2,14 +2,14 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::{SubregionOrigin, TypeTrace}; +use crate::traits::ObligationCauseCode; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; -use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{ - GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef, - TyKind, -}; -use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor}; +use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; +use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; +use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; +use rustc_span::Span; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -27,6 +27,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) if **sub_r == RegionKind::ReStatic => { (var_origin, sub_origin, sub_r, sup_origin, sup_r) } + RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(box TypeTrace { cause, .. }), + sub_r, + sup_r, + ) if **sub_r == RegionKind::ReStatic => { + // This is for the implicit `'static` requirement coming from `impl dyn Trait {}`. + if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + let param = self.find_param_with_region(sup_r, sub_r)?; + let lifetime = if sup_r.has_name() { + format!("lifetime `{}`", sup_r) + } else { + "an anonymous lifetime `'_`".to_string() + }; + let mut err = struct_span_err!( + tcx.sess, + cause.span, + E0759, + "cannot infer an appropriate lifetime" + ); + err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + err.span_label( + cause.span, + "...is captured and required to live as long as `'static` here", + ); + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) { + err.emit(); + return Some(ErrorReported); + } else { + err.cancel(); + } + } + return None; + } _ => return None, }; debug!( @@ -96,7 +129,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - self.find_impl_on_dyn_trait(&mut err, param.param_ty); + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { + if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container); + } + } let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); @@ -222,63 +259,86 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default /// `'static` obligation. Find `impl` blocks that are implemented - fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool { + fn find_impl_on_dyn_trait( + &self, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + container: &AssocItemContainer, + ) -> bool { let tcx = self.tcx(); + let mut suggested = false; // Find the trait object types in the argument. let mut v = TraitObjectVisitor(vec![]); v.visit_ty(ty); - debug!("TraitObjectVisitor {:?}", v.0); - // Find all the `impl`s in the local scope that can be called on the type parameter. - // FIXME: this doesn't find `impl dyn Trait { /**/ }`. + let container_id = match container { + // When the obligation comes from an `impl Foo for dyn Bar {}`, we + // have the `DefId` of the `trait` itself, not the relevant `impl` + // block. Because of this, we have to look at all the `trait`s + // available, and filter out all that are not of `Foo` (this `def_id`) + // and not of `Bar` (the `filter_map` later in this method). + AssocItemContainer::TraitContainer(def_id) => def_id, + + // When the obligation comes from an `impl dyn Trait {}`, we already + // have the `DefId` of the relevant `Item`, so we use it directly. + AssocItemContainer::ImplContainer(def_id) => { + if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = + tcx.hir().get_if_local(*def_id) + { + for found_did in &v.0 { + let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + hir_v.visit_ty(self_ty); + if let [span] = &hir_v.0[..] { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "this `impl` introduces an implicit `'static` requirement, \ + consider changing it", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; + } + } + } + return suggested; + } + }; + + // Find all the `impl`s in the local scope that can be called on the type parameter. And + // retain all that are `impl`s of the trait that originated the `'static` obligation. + // This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above. let impl_self_tys = tcx .all_traits(LOCAL_CRATE) .iter() .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did)) .filter_map(|impl_node| { let impl_did = tcx.hir().local_def_id(*impl_node); - if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = - tcx.hir().get_if_local(impl_did.to_def_id()) - { - Some(self_ty) - } else { - None + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. }, + .. + })) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty), + _ => None, } }); - let mut suggested = false; + + // Given all the `impl`s of the relevant `trait`, look for those that are implemented for + // the trait object in the `fn` parameter type. for self_ty in impl_self_tys { - if let TyKind::TraitObject( - poly_trait_refs, - Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, - ) = self_ty.kind - { - for p in poly_trait_refs { - if let PolyTraitRef { - trait_ref: - TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. }, - .. - } = p - { - for found_did in &v.0 { - if did == found_did { - // We've found an `impl Foo for dyn Bar {}`. - // FIXME: we should change this so it also works for - // `impl Foo for Box {}`. - err.span_suggestion_verbose( - self_ty.span.shrink_to_hi(), - "this `impl` introduces an implicit `'static` requirement, \ - consider changing it", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } - } - } + for found_did in &v.0 { + let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + hir_v.visit_ty(self_ty); + if let [span] = &hir_v.0[..] { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "this `impl` introduces an implicit `'static` requirement, \ + consider changing it", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; } - err.emit(); - return Some(ErrorReported); } } suggested @@ -301,3 +361,31 @@ impl TypeVisitor<'_> for TraitObjectVisitor { } } } + +/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime. +struct HirTraitObjectVisitor(Vec, DefId); + +impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor { + type Map = ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + match t.kind { + TyKind::TraitObject( + poly_trait_refs, + Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) => { + for ptr in poly_trait_refs { + if Some(self.1) == ptr.trait_ref.trait_def_id() { + self.0.push(ptr.span); + } + } + } + _ => {} + } + walk_ty(self, t); + } +} diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index fa999abb1a86c..28e9dd90cfd67 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, DefIdTree, Region, Ty}; use rustc_span::Span; -// The struct contains the information about the anonymous region -// we are searching for. +/// Information about the anonymous region we are searching for. #[derive(Debug)] pub(super) struct AnonymousParamInfo<'tcx> { - // the parameter corresponding to the anonymous region + /// The parameter corresponding to the anonymous region. pub param: &'tcx hir::Param<'tcx>, - // the type corresponding to the anonymopus region parameter + /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, - // the ty::BoundRegion corresponding to the anonymous region + /// The ty::BoundRegion corresponding to the anonymous region. pub bound_region: ty::BoundRegion, - // param_ty_span contains span of parameter type + /// The `Span` of the parameter type. pub param_ty_span: Span, - // corresponds to id the argument is the first parameter - // in the declaration + /// Signals that the argument is the first parameter in the declaration. pub is_first: bool, } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 37883fcb07468..3744ad5d0324a 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -463,7 +463,7 @@ pub enum RegionVariableOrigin { AddrOfRegion(Span), /// Regions created as part of an autoref of a method receiver - Autoref(Span), + Autoref(Span, ty::AssocItem), /// Regions created as part of an automatic coercion Coercion(Span), @@ -1800,15 +1800,15 @@ impl<'tcx> SubregionOrigin<'tcx> { impl RegionVariableOrigin { pub fn span(&self) -> Span { match *self { - MiscVariable(a) => a, - PatternRegion(a) => a, - AddrOfRegion(a) => a, - Autoref(a) => a, - Coercion(a) => a, - EarlyBoundRegion(a, ..) => a, - LateBoundRegion(a, ..) => a, + MiscVariable(a) + | PatternRegion(a) + | AddrOfRegion(a) + | Autoref(a, _) + | Coercion(a) + | EarlyBoundRegion(a, ..) + | LateBoundRegion(a, ..) + | UpvarRegion(_, a) => a, BoundRegionInCoherence(_) => rustc_span::DUMMY_SP, - UpvarRegion(_, a) => a, NLL(..) => bug!("NLL variable used with `span`"), } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 0cd6585163c4e..bacb7fa153e43 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -13,6 +13,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bindings_after_at)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index c15c31a53f0c9..c066ea831b298 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> { /// Method receiver MethodReceiver, + UnifyReceiver(Rc), + /// `return` with no expression ReturnNoExpression, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 334462790edbc..61ef0821733e8 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -213,6 +213,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::StartFunctionType => Some(super::StartFunctionType), super::IntrinsicType => Some(super::IntrinsicType), super::MethodReceiver => Some(super::MethodReceiver), + super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 51a353c013241..9007bd99d7e4b 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -136,7 +136,7 @@ pub struct ResolverOutputs { pub extern_prelude: FxHashMap, } -#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)] pub enum AssocItemContainer { TraitContainer(DefId), ImplContainer(DefId), @@ -184,7 +184,7 @@ pub enum ImplPolarity { Reservation, } -#[derive(Copy, Clone, Debug, PartialEq, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)] pub struct AssocItem { pub def_id: DefId, #[stable_hasher(project(name))] @@ -199,7 +199,7 @@ pub struct AssocItem { pub fn_has_self_parameter: bool, } -#[derive(Copy, Clone, PartialEq, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)] pub enum AssocKind { Const, Fn, @@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> { } } -#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)] pub enum Visibility { /// Visible everywhere (including in other crates). Public, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 0a6fb72ca51ea..e94b44d879533 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression + | ObligationCauseCode::UnifyReceiver(_) | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 96248e18aaf87..58cbe8b2479d6 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -6,6 +6,7 @@ use crate::hir::def_id::DefId; use crate::hir::GenericArg; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; @@ -15,6 +16,7 @@ use rustc_span::Span; use rustc_trait_selection::traits; use std::ops::Deref; +use std::rc::Rc; struct ConfirmContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -91,7 +93,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // signature (which is also done during probing). let method_sig_rcvr = self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]); - self.unify_receivers(self_ty, method_sig_rcvr); + debug!( + "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", + self_ty, method_sig_rcvr, method_sig, method_predicates + ); + self.unify_receivers(self_ty, method_sig_rcvr, &pick); let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); @@ -150,7 +156,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); if let Some(mutbl) = pick.autoref { - let region = self.next_region_var(infer::Autoref(self.span)); + let region = self.next_region_var(infer::Autoref(self.span, pick.item)); target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target }); let mutbl = match mutbl { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -334,8 +340,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) } - fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { - match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) { + fn unify_receivers( + &mut self, + self_ty: Ty<'tcx>, + method_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + ) { + debug!( + "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}", + self_ty, method_self_ty, self.span, pick + ); + let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item))); + match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs deleted file mode 100644 index dd53ee06ff5ee..0000000000000 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs +++ /dev/null @@ -1,14 +0,0 @@ -trait OtherTrait<'a> {} -impl<'a> OtherTrait<'a> for &'a () {} - -trait ObjectTrait {} - -impl dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } -} - -fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR mismatched types -} - -fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr deleted file mode 100644 index 4618b540c70ee..0000000000000 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9 - | -LL | val.use_self() - | ^^^^^^^^ lifetime mismatch - | - = note: expected reference `&(dyn ObjectTrait + 'static)` - found reference `&(dyn ObjectTrait + 'a)` -note: the lifetime `'a` as defined on the function body at 10:11... - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11 - | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | ^^ - = note: ...does not necessarily outlive the static lifetime - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index dfe475d3c0694..62cf9b989bb4d 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -9,10 +9,12 @@ mod foo { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait + '_ { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { val.use_self() //~ ERROR cannot infer an appropriate lifetime @@ -24,14 +26,48 @@ mod bar { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait + '_ { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() //~ ERROR cannot infer an appropriate lifetime } } +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr new file mode 100644 index 0000000000000..00f65a2348935 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self() + | ^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self() + | ^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index 85e6c2993b9b1..28a599d12bfd1 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -9,10 +9,12 @@ mod foo { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { val.use_self() //~ ERROR cannot infer an appropriate lifetime @@ -24,14 +26,48 @@ mod bar { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() //~ ERROR cannot infer an appropriate lifetime } } +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 6780459adbeac..1a03590febe46 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -1,5 +1,5 @@ error[E0759]: cannot infer an appropriate lifetime - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | ------------------- this data with lifetime `'a`... @@ -12,7 +12,20 @@ LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ error[E0759]: cannot infer an appropriate lifetime - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl dyn ObjectTrait + '_ { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { | ------------------- this data with lifetime `'a`... @@ -24,6 +37,19 @@ help: this `impl` introduces an implicit `'static` requirement, consider changin LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error: aborting due to 2 previous errors +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13 + | +LL | fn use_it<'a>(val: &'a Box) -> &'a () { + | ----------------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl MyTrait for Box { + | ^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0759`. From 6bac3dbfc2c34ce1337bc6cdde36aaeb3b6deba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Jun 2020 18:07:26 -0700 Subject: [PATCH 15/22] Add more context to diagnostic --- .../nice_region_error/static_impl_trait.rs | 78 +++++++++++++++---- ...yn-trait-with-implicit-static-bound.stderr | 36 ++++++++- 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 0aa1d65612ee6..36d354ea777a4 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -8,8 +8,10 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorRepor use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; -use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; -use rustc_span::Span; +use rustc_middle::ty::{ + self, AssocItem, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor, +}; +use rustc_span::{MultiSpan, Span}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -51,7 +53,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { cause.span, "...is captured and required to live as long as `'static` here", ); - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) { err.emit(); return Some(ErrorReported); } else { @@ -131,7 +133,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { - self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container); + self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc); } } @@ -263,7 +265,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, - container: &AssocItemContainer, + assoc: &AssocItem, ) -> bool { let tcx = self.tcx(); let mut suggested = false; @@ -272,7 +274,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut v = TraitObjectVisitor(vec![]); v.visit_ty(ty); - let container_id = match container { + let container_id = match assoc.container { // When the obligation comes from an `impl Foo for dyn Bar {}`, we // have the `DefId` of the `trait` itself, not the relevant `impl` // block. Because of this, we have to look at all the `trait`s @@ -284,16 +286,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // have the `DefId` of the relevant `Item`, so we use it directly. AssocItemContainer::ImplContainer(def_id) => { if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = - tcx.hir().get_if_local(*def_id) + tcx.hir().get_if_local(def_id) { for found_did in &v.0 { let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); hir_v.visit_ty(self_ty); if let [span] = &hir_v.0[..] { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this trait object has an implicit `'static` lifetime requirement" + .to_string(), + ); + multi_span.push_span_label( + assoc.ident.span, + "the `'static` requirement is introduced when calling this method" + .to_string(), + ); + err.span_note( + multi_span, + &format!( + "when using method `{}` on `{}`, an implicit `'static` \ + requirement is introduced", + assoc.ident, + tcx.def_path_str(*found_did), + ), + ); err.span_suggestion_verbose( span.shrink_to_hi(), - "this `impl` introduces an implicit `'static` requirement, \ - consider changing it", + "consider relaxing the implicit `'static` requirement", " + '_".to_string(), Applicability::MaybeIncorrect, ); @@ -316,24 +337,53 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let impl_did = tcx.hir().local_def_id(*impl_node); match tcx.hir().get_if_local(impl_did.to_def_id()) { Some(Node::Item(Item { - kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. }, + kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), items, .. }, .. - })) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty), + })) if of_trait.trait_def_id() == Some(container_id) => Some(( + self_ty, + // Get the ident of the method, in order to use its `Span`. + items + .iter() + .filter(|item| item.ident == assoc.ident) + .map(|item| item.ident) + .next() + .unwrap_or(assoc.ident), + )), _ => None, } }); // Given all the `impl`s of the relevant `trait`, look for those that are implemented for // the trait object in the `fn` parameter type. - for self_ty in impl_self_tys { + for (self_ty, method) in impl_self_tys { for found_did in &v.0 { let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); hir_v.visit_ty(self_ty); if let [span] = &hir_v.0[..] { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this trait object has an implicit `'static` lifetime requirement" + .to_string(), + ); + multi_span.push_span_label( + method.span, + "the `'static` requirement is introduced when calling this method" + .to_string(), + ); + err.span_note( + multi_span, + &format!( + "when using method `{}` of trait `{}` on `{}`, an implicit `'static` \ + requirement is introduced", + method, + tcx.def_path_str(container_id), + tcx.def_path_str(*found_did), + ), + ); err.span_suggestion_verbose( span.shrink_to_hi(), - "this `impl` introduces an implicit `'static` requirement, \ - consider changing it", + "consider relaxing the implicit `'static` requirement", " + '_".to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 1a03590febe46..8f8fd9dc32402 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -6,7 +6,14 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -help: this `impl` introduces an implicit `'static` requirement, consider changing it +note: when using method `use_self` of trait `foo::MyTrait` on `foo::ObjectTrait`, an implicit `'static` requirement is introduced + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- the `'static` requirement is introduced when calling this method +help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ @@ -19,7 +26,14 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -help: this `impl` introduces an implicit `'static` requirement, consider changing it +note: when using method `use_self` on `bat::ObjectTrait`, an implicit `'static` requirement is introduced + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- the `'static` requirement is introduced when calling this method +help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { | ^^^^ @@ -32,7 +46,14 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -help: this `impl` introduces an implicit `'static` requirement, consider changing it +note: when using method `use_self` of trait `bar::MyTrait` on `bar::ObjectTrait`, an implicit `'static` requirement is introduced + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- the `'static` requirement is introduced when calling this method +help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ @@ -45,7 +66,14 @@ LL | fn use_it<'a>(val: &'a Box) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -help: this `impl` introduces an implicit `'static` requirement, consider changing it +note: when using method `use_self` of trait `baz::MyTrait` on `baz::ObjectTrait`, an implicit `'static` requirement is introduced + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 + | +LL | impl MyTrait for Box { + | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- the `'static` requirement is introduced when calling this method +help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for Box { | ^^^^ From 7bf39fa9d965535f815326e3f1c48799b8077ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jun 2020 11:14:42 -0700 Subject: [PATCH 16/22] Further tweak wording of E0759 and introduce E0767 --- src/librustc_error_codes/error_codes.rs | 1 + .../nice_region_error/static_impl_trait.rs | 107 +++++++++++++----- ...ject-fn-ret-contravariant.transmute.stderr | 2 +- .../project-fn-ret-invariant.transmute.stderr | 2 +- src/test/ui/async-await/issues/issue-62097.rs | 2 +- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../impl-header-lifetime-elision/dyn-trait.rs | 2 +- .../dyn-trait.stderr | 2 +- ...t_outlive_least_region_or_bound.nll.stderr | 16 +-- .../must_outlive_least_region_or_bound.rs | 32 ++---- .../must_outlive_least_region_or_bound.stderr | 58 +++++----- .../static-return-lifetime-infered.nll.stderr | 2 +- .../static-return-lifetime-infered.rs | 6 +- .../static-return-lifetime-infered.stderr | 8 +- src/test/ui/issues/issue-16922.rs | 3 +- src/test/ui/issues/issue-16922.stderr | 2 +- .../constant-in-expr-inherent-1.stderr | 2 +- .../object-lifetime-default-from-box-error.rs | 2 +- ...ect-lifetime-default-from-box-error.stderr | 2 +- .../region-object-lifetime-in-coercion.rs | 6 +- .../region-object-lifetime-in-coercion.stderr | 6 +- src/test/ui/regions/regions-addr-of-self.rs | 2 +- .../ui/regions/regions-addr-of-self.stderr | 2 +- .../regions-close-object-into-object-2.rs | 2 +- .../regions-close-object-into-object-2.stderr | 2 +- .../regions-close-object-into-object-4.rs | 2 +- .../regions-close-object-into-object-4.stderr | 2 +- .../ui/regions/regions-proc-bound-capture.rs | 2 +- .../regions/regions-proc-bound-capture.stderr | 2 +- ...elf_types_pin_lifetime_impl_trait-async.rs | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ...rary_self_types_pin_lifetime_impl_trait.rs | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 2 +- ...dyn-trait-with-implicit-static-bound.fixed | 29 ++++- ...rait-with-implicit-static-bound.nll.stderr | 12 +- ...on-dyn-trait-with-implicit-static-bound.rs | 29 ++++- ...yn-trait-with-implicit-static-bound.stderr | 64 +++++++---- .../missing-lifetimes-in-signature.rs | 2 +- .../missing-lifetimes-in-signature.stderr | 2 +- .../trait-object-nested-in-impl-trait.rs | 8 +- .../trait-object-nested-in-impl-trait.stderr | 8 +- .../dyn-trait-underscore.rs | 2 +- .../dyn-trait-underscore.stderr | 2 +- 43 files changed, 280 insertions(+), 167 deletions(-) diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 279c65ce03d2d..7c762a3415e13 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -633,4 +633,5 @@ E0771: include_str!("./error_codes/E0771.md"), E0755, // `#[ffi_pure]` is only allowed on foreign functions E0756, // `#[ffi_const]` is only allowed on foreign functions E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]` + E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 36d354ea777a4..9fa905cb5abe9 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -45,13 +45,31 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut err = struct_span_err!( tcx.sess, cause.span, - E0759, - "cannot infer an appropriate lifetime" + E0767, + "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ + requirement", + param + .param + .pat + .simple_ident() + .map(|s| format!("`{}`", s)) + .unwrap_or_else(|| "`fn` parameter".to_string()), + lifetime, + assoc.ident, ); err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); err.span_label( cause.span, - "...is captured and required to live as long as `'static` here", + &format!( + "...is captured and required to live as long as `'static` here \ + because of an implicit lifetime bound on the {}", + match assoc.container { + AssocItemContainer::TraitContainer(id) => + format!("`impl` of `{}`", tcx.def_path_str(id)), + AssocItemContainer::ImplContainer(_) => + "inherent `impl`".to_string(), + }, + ), ); if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) { err.emit(); @@ -78,10 +96,49 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } else { ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) }; - let mut err = struct_span_err!(tcx.sess, sp, E0759, "cannot infer an appropriate lifetime"); + let param_name = param + .param + .pat + .simple_ident() + .map(|s| format!("`{}`", s)) + .unwrap_or_else(|| "`fn` parameter".to_string()); + let mut err = struct_span_err!( + tcx.sess, + sp, + E0759, + "{} has {} but it needs to satisfy a `'static` lifetime requirement", + param_name, + lifetime, + ); err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); debug!("try_report_static_impl_trait: param_info={:?}", param); + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); + + let mut postfix = String::new(); + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { + if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) + && fn_returns.is_empty() + { + err.code(rustc_errors::error_code!(E0767)); + err.set_primary_message(&format!( + "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ + requirement", + param_name, lifetime, assoc.ident, + )); + postfix = format!( + " because of an implicit lifetime on the {}", + match assoc.container { + AssocItemContainer::TraitContainer(id) => + format!("`impl` of `{}`", tcx.def_path_str(id)), + AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), + }, + ); + } + } + } + // We try to make the output have fewer overlapping spans if possible. if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) && sup_origin.span() != return_sp @@ -108,36 +165,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | ---- ^ err.span_label( sup_origin.span(), - "...is captured here, requiring it to live as long as `'static`", + &format!( + "...is captured here, requiring it to live as long as `'static`{}", + postfix + ), ); } else { err.span_label(sup_origin.span(), "...is captured here..."); if return_sp < sup_origin.span() { err.span_note( return_sp, - "...and is required to live as long as `'static` here", + &format!("...and is required to live as long as `'static` here{}", postfix), ); } else { err.span_label( return_sp, - "...and is required to live as long as `'static` here", + &format!("...and is required to live as long as `'static` here{}", postfix), ); } } } else { err.span_label( return_sp, - "...is captured and required to live as long as `'static` here", + &format!( + "...is captured and required to live as long as `'static` here{}", + postfix + ), ); } - if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { - self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc); - } - } - - let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` let consider = "consider changing the"; @@ -295,20 +351,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut multi_span: MultiSpan = vec![*span].into(); multi_span.push_span_label( *span, - "this trait object has an implicit `'static` lifetime requirement" - .to_string(), + "this has an implicit `'static` lifetime requirement".to_string(), ); multi_span.push_span_label( assoc.ident.span, - "the `'static` requirement is introduced when calling this method" + "`'static` requirement is introduced when calling this method" .to_string(), ); err.span_note( multi_span, &format!( - "when using method `{}` on `{}`, an implicit `'static` \ - requirement is introduced", - assoc.ident, + "`{}`'s inherent `impl` has a `'static` requirement", tcx.def_path_str(*found_did), ), ); @@ -363,22 +416,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut multi_span: MultiSpan = vec![*span].into(); multi_span.push_span_label( *span, - "this trait object has an implicit `'static` lifetime requirement" - .to_string(), + "this has an implicit `'static` lifetime requirement".to_string(), ); multi_span.push_span_label( method.span, - "the `'static` requirement is introduced when calling this method" - .to_string(), + "`'static` requirement is introduced when calling this method".to_string(), ); err.span_note( multi_span, &format!( - "when using method `{}` of trait `{}` on `{}`, an implicit `'static` \ - requirement is introduced", - method, - tcx.def_path_str(container_id), + "`{}`'s `impl` of `{}` has an implicit `'static` requirement", tcx.def_path_str(*found_did), + tcx.def_path_str(container_id), ), ); err.span_suggestion_verbose( diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 36812d3c0441e..0be9b37263a48 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/project-fn-ret-contravariant.rs:38:8 | LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 9cec0780b3ca8..0a44864b24955 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/project-fn-ret-invariant.rs:49:9 | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs index ea482d3667e2b..66ebbd83ffa9e 100644 --- a/src/test/ui/async-await/issues/issue-62097.rs +++ b/src/test/ui/async-await/issues/issue-62097.rs @@ -9,7 +9,7 @@ where struct Struct; impl Struct { - pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer + pub async fn run_dummy_fn(&self) { //~ ERROR E0759 foo(|| self.bar()).await; } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 0f58b158904db..56a28d904b91d 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs index d4ad706d01bc2..89210fdf137e0 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs @@ -17,7 +17,7 @@ fn static_val(_: T) { } fn with_dyn_debug_static<'a>(x: Box) { - static_val(x); //~ ERROR cannot infer + static_val(x); //~ ERROR E0759 } fn not_static_val(_: T) { diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index 397cb3750c266..b3bef677d19c1 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/dyn-trait.rs:20:16 | LL | fn with_dyn_debug_static<'a>(x: Box) { diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 3b339c5c3d7fc..4372de245078f 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -12,7 +12,7 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:5:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | -- ^^^^^^^^^ opaque type requires that `'a` must outlive `'static` @@ -26,7 +26,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + --> $DIR/must_outlive_least_region_or_bound.rs:7:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | - ^ returning this value requires that `'1` must outlive `'static` @@ -36,7 +36,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } = help: consider replacing `'1` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + --> $DIR/must_outlive_least_region_or_bound.rs:9:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -45,7 +45,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } = help: consider replacing `'a` with `'static` error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:15:41 + --> $DIR/must_outlive_least_region_or_bound.rs:11:41 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^ lifetime `'a` required @@ -53,7 +53,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:30:24 + --> $DIR/must_outlive_least_region_or_bound.rs:22:24 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` @@ -61,7 +61,7 @@ LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | let's call the lifetime of this reference `'1` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:37:69 + --> $DIR/must_outlive_least_region_or_bound.rs:28:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -70,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:42:61 + --> $DIR/must_outlive_least_region_or_bound.rs:32:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -80,7 +80,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:47:51 + --> $DIR/must_outlive_least_region_or_bound.rs:37:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 9bf86fa66cded..51f488e45a6f3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -1,41 +1,31 @@ use std::fmt::Debug; -fn elided(x: &i32) -> impl Copy { x } -//~^ ERROR cannot infer an appropriate lifetime +fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759 -fn explicit<'a>(x: &'a i32) -> impl Copy { x } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759 -fn elided2(x: &i32) -> impl Copy + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759 -fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } //~ ERROR E0759 fn foo<'a>(x: &i32) -> impl Copy + 'a { x } //~^ ERROR explicit lifetime required in the type of `x` -fn elided3(x: &i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn elided3(x: &i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn elided4(x: &i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn elided4(x: &i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } -//~^ ERROR cannot infer an appropriate lifetime +fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~ ERROR E0759 -fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } -//~^ ERROR cannot infer an appropriate lifetime -//~| ERROR cannot infer an appropriate lifetime +fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } //~ ERROR E0759 +//~^ ERROR E0759 trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} -fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } -//~^ ERROR cannot infer an appropriate lifetime +fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERROR E0759 // Tests that a closure type containing 'b cannot be returned from a type where // only 'a was expected. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index ffadcaae08e05..b040889217e47 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } @@ -16,8 +16,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:6:44 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:5:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- ^ ...is captured here... @@ -25,7 +25,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | this data with lifetime `'a`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:5:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ^^^^^^^^^ @@ -34,8 +34,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:9:46 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:7:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ^ ...is captured here... @@ -43,7 +43,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | this data with an anonymous lifetime `'_`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:9:24 + --> $DIR/must_outlive_least_region_or_bound.rs:7:24 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -56,8 +56,8 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:12:55 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:9:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ^ ...is captured here... @@ -65,7 +65,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | this data with lifetime `'a`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:12:33 + --> $DIR/must_outlive_least_region_or_bound.rs:9:33 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -79,15 +79,15 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:15:24 + --> $DIR/must_outlive_least_region_or_bound.rs:11:24 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^^^^^^^^^^^^^^ lifetime `'a` required | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:30:65 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:22:65 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` @@ -101,14 +101,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:30:69 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:22:69 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:30:41 + --> $DIR/must_outlive_least_region_or_bound.rs:22:41 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ^^^^^^^^^^ @@ -121,14 +121,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:37:69 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:28:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- this data with lifetime `'a`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:37:34 + --> $DIR/must_outlive_least_region_or_bound.rs:28:34 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:42:61 + --> $DIR/must_outlive_least_region_or_bound.rs:32:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -151,15 +151,15 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:47:51 + --> $DIR/must_outlive_least_region_or_bound.rs:37:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:18:50 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:14:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -171,8 +171,8 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:21:59 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:16:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- ^ ...is captured here, requiring it to live as long as `'static` @@ -184,8 +184,8 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:24:60 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:18:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -201,8 +201,8 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:27:69 +error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/must_outlive_least_region_or_bound.rs:20:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 123ea6af6b019..65178cc9d24c2 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -12,7 +12,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/static-return-lifetime-infered.rs:10:37 + --> $DIR/static-return-lifetime-infered.rs:9:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -- ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index 96f3652c226ea..518c52f5de4d7 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -4,13 +4,11 @@ struct A { impl A { fn iter_values_anon(&self) -> impl Iterator { - self.x.iter().map(|a| a.0) + self.x.iter().map(|a| a.0) //~ ERROR E0759 } - //~^^ ERROR cannot infer an appropriate lifetime fn iter_values<'a>(&'a self) -> impl Iterator { - self.x.iter().map(|a| a.0) + self.x.iter().map(|a| a.0) //~ ERROR E0759 } - //~^^ ERROR cannot infer an appropriate lifetime } fn main() {} diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index df0db6e4fc6df..7c289b388223a 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { @@ -18,8 +18,8 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime - --> $DIR/static-return-lifetime-infered.rs:11:16 +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/static-return-lifetime-infered.rs:10:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -------- this data with lifetime `'a`... @@ -29,7 +29,7 @@ LL | self.x.iter().map(|a| a.0) | ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/static-return-lifetime-infered.rs:10:37 + --> $DIR/static-return-lifetime-infered.rs:9:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs index 827163ef83cf7..f048ccd2427cb 100644 --- a/src/test/ui/issues/issue-16922.rs +++ b/src/test/ui/issues/issue-16922.rs @@ -1,8 +1,7 @@ use std::any::Any; fn foo(value: &T) -> Box { - Box::new(value) as Box - //~^ ERROR cannot infer an appropriate lifetime + Box::new(value) as Box //~ ERROR E0759 } fn main() { diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 919594fc9af4b..6decc751321f9 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index f823f69c76f67..1931934a2112a 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/constant-in-expr-inherent-1.rs:8:5 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs index 708ab1cf38297..4a2665d8e1694 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box { // `Box` defaults to a `'static` bound, so this return // is illegal. - ss.r //~ ERROR cannot infer an appropriate lifetime + ss.r //~ ERROR E0759 } fn store(ss: &mut SomeStruct, b: Box) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 1b1e0d9610724..70b99ef7869ca 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `ss` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index 5d199149c39b8..9d3f485e31438 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -5,18 +5,18 @@ trait Foo {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { - let x: Box = Box::new(v); //~ ERROR cannot infer an appropriate lifetime + let x: Box = Box::new(v); //~ ERROR E0759 x } fn b(v: &[u8]) -> Box { - Box::new(v) //~ ERROR cannot infer an appropriate lifetime + Box::new(v) //~ ERROR E0759 } fn c(v: &[u8]) -> Box { // same as previous case due to RFC 599 - Box::new(v) //~ ERROR cannot infer an appropriate lifetime + Box::new(v) //~ ERROR E0759 } fn d<'a,'b>(v: &'a [u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 7f5a3a47976c7..63fea1f41626d 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { @@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { @@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-addr-of-self.rs b/src/test/ui/regions/regions-addr-of-self.rs index 647212407fc8a..4eb1b275f163e 100644 --- a/src/test/ui/regions/regions-addr-of-self.rs +++ b/src/test/ui/regions/regions-addr-of-self.rs @@ -4,7 +4,7 @@ struct Dog { impl Dog { pub fn chase_cat(&mut self) { - let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer + let p: &'static mut usize = &mut self.cats_chased; //~ ERROR E0759 *p += 1; } diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr index c15a933379c85..738691fd695eb 100644 --- a/src/test/ui/regions/regions-addr-of-self.stderr +++ b/src/test/ui/regions/regions-addr-of-self.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-addr-of-self.rs:7:37 | LL | pub fn chase_cat(&mut self) { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs index 2364ba2728600..7144ab5a24c51 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.rs +++ b/src/test/ui/regions/regions-close-object-into-object-2.rs @@ -7,7 +7,7 @@ trait X { } impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - box B(&*v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR E0759 } fn main() { } diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 114e4052aae09..aab7ce993aa3c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs index d531077043686..4c087f264f92b 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.rs +++ b/src/test/ui/regions/regions-close-object-into-object-4.rs @@ -7,7 +7,7 @@ trait X { } impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { - box B(&*v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR E0759 } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 850d81940791f..90f807a41c562 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs index 8617c0e9da8f7..55d964ac53405 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.rs +++ b/src/test/ui/regions/regions-proc-bound-capture.rs @@ -6,7 +6,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { fn static_proc(x: &isize) -> Box (isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime + Box::new(move || { *x }) //~ ERROR E0759 } fn main() { } diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 67eee3bb6e281..e76073f4f6b13 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs index 0afe631f1e3fc..43998ca8c5784 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -6,7 +6,7 @@ struct Foo; impl Foo { async fn f(self: Pin<&Self>) -> impl Clone { self } - //~^ ERROR cannot infer an appropriate lifetime + //~^ ERROR E0759 } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index f2fbb0ba7d755..9cd0fd328ffa0 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs index 5054568b18970..04935fc52ab9e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs @@ -3,7 +3,7 @@ use std::pin::Pin; struct Foo; impl Foo { - fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime + fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759 } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 2e10ab3d3f9b8..cb9d5b56dbc5c 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index 62cf9b989bb4d..832b185e619fa 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -17,7 +17,7 @@ mod foo { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0759 } } @@ -34,7 +34,7 @@ mod bar { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } @@ -51,7 +51,7 @@ mod baz { impl Irrelevant for Box {} fn use_it<'a>(val: &'a Box) -> &'a () { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } @@ -66,8 +66,29 @@ mod bat { } fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0759 + } +} + + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index 00f65a2348935..8765591c4a114 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -18,5 +18,15 @@ LL | val.use_self() | = help: consider replacing `'a` with `'static` -error: aborting due to 2 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self() + | ^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index 28a599d12bfd1..ba26c2d67dfa8 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -17,7 +17,7 @@ mod foo { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0759 } } @@ -34,7 +34,7 @@ mod bar { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } @@ -51,7 +51,7 @@ mod baz { impl Irrelevant for Box {} fn use_it<'a>(val: &'a Box) -> &'a () { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } @@ -66,8 +66,29 @@ mod bat { } fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR cannot infer an appropriate lifetime + val.use_self() //~ ERROR E0767 } } +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR E0759 + } +} + + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 8f8fd9dc32402..425159edbcd4a 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { @@ -6,78 +6,102 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: when using method `use_self` of trait `foo::MyTrait` on `foo::ObjectTrait`, an implicit `'static` requirement is introduced +note: `foo::ObjectTrait`'s `impl` of `foo::MyTrait` has an implicit `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- the `'static` requirement is introduced when calling this method + | -------- `'static` requirement is introduced when calling this method help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | ------------------- this data with lifetime `'a`... LL | val.use_self() - | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl` | -note: when using method `use_self` on `bat::ObjectTrait`, an implicit `'static` requirement is introduced +note: `bat::ObjectTrait`'s inherent `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 | LL | impl dyn ObjectTrait { - | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- the `'static` requirement is introduced when calling this method + | -------- `'static` requirement is introduced when calling this method help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:13 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | ------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: `ban::ObjectTrait`'s `impl` of `ban::MyTrait` has an implicit `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- `'static` requirement is introduced when calling this method +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { | ------------------- this data with lifetime `'a`... LL | val.use_self() - | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait` | -note: when using method `use_self` of trait `bar::MyTrait` on `bar::ObjectTrait`, an implicit `'static` requirement is introduced +note: `bar::ObjectTrait`'s `impl` of `bar::MyTrait` has an implicit `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- the `'static` requirement is introduced when calling this method + | -------- `'static` requirement is introduced when calling this method help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13 | LL | fn use_it<'a>(val: &'a Box) -> &'a () { | ----------------------------- this data with lifetime `'a`... LL | val.use_self() - | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait` | -note: when using method `use_self` of trait `baz::MyTrait` on `baz::ObjectTrait`, an implicit `'static` requirement is introduced +note: `baz::ObjectTrait`'s `impl` of `baz::MyTrait` has an implicit `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 | LL | impl MyTrait for Box { - | ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- the `'static` requirement is introduced when calling this method + | -------- `'static` requirement is introduced when calling this method help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for Box { | ^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index d3853445dfdfe..94dd826a15cae 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -16,7 +16,7 @@ fn foo(g: G, dest: &mut T) -> impl FnOnce() where G: Get { - move || { //~ ERROR cannot infer an appropriate lifetime + move || { //~ ERROR `dest` *dest = g.get(); } } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 9ab060328537b..d7051515f1102 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,7 +6,7 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs index f78edb1c83a4c..d8446e58dbb63 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -27,7 +27,7 @@ impl Bar { fn iter(&self) -> impl Iterator> { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -38,7 +38,7 @@ impl Baz { fn iter(&self) -> impl Iterator> + '_ { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -49,7 +49,7 @@ impl Bat { fn iter<'a>(&'a self) -> impl Iterator> + 'a { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } @@ -60,7 +60,7 @@ impl Ban { fn iter<'a>(&'a self) -> impl Iterator> { Iter { current: None, - remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + remaining: self.0.iter(), //~ ERROR E0759 } } } diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index 1257e9b172cf7..9f30787f07cc6 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:30:31 | LL | fn iter(&self) -> impl Iterator> { @@ -23,7 +23,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter(&self) -> impl Iterator> { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:41:31 | LL | fn iter(&self) -> impl Iterator> + '_ { @@ -44,7 +44,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter(&self) -> impl Iterator> + '_ { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:52:31 | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { @@ -65,7 +65,7 @@ help: to declare that the trait object captures data from argument `self`, you c LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { | ^^^^ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/trait-object-nested-in-impl-trait.rs:63:31 | LL | fn iter<'a>(&'a self) -> impl Iterator> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index d5aa18eb0f4e7..e951adf030f5c 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -5,7 +5,7 @@ fn a(items: &[T]) -> Box> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` - Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + Box::new(items.iter()) //~ ERROR E0759 } fn b(items: &[T]) -> Box + '_> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index dda5de431d309..dd804864dab4f 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,4 +1,4 @@ -error[E0759]: cannot infer an appropriate lifetime +error[E0759]: `items` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { From f80743712eea6e90c4fd73b596bf45c43d9c9e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jun 2020 17:41:15 -0700 Subject: [PATCH 17/22] Use `ty::Instance::resolve` to identify `'static` bound source --- .../nice_region_error/static_impl_trait.rs | 221 ++++++++---------- src/librustc_middle/traits/mod.rs | 9 +- .../traits/structural_impls.rs | 15 +- .../traits/codegen/mod.rs | 13 ++ .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 15 +- ...dyn-trait-with-implicit-static-bound.fixed | 23 +- ...rait-with-implicit-static-bound.nll.stderr | 10 +- ...on-dyn-trait-with-implicit-static-bound.rs | 23 +- ...yn-trait-with-implicit-static-bound.stderr | 47 ++-- 10 files changed, 196 insertions(+), 182 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9fa905cb5abe9..9c2e02968f607 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -3,18 +3,20 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; -use crate::traits::ObligationCauseCode; +use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; -use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; -use rustc_middle::ty::{ - self, AssocItem, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor, +use rustc_hir::{ + self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem, + TyKind, }; +use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; use rustc_span::{MultiSpan, Span}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - /// Print the error message for lifetime errors when the return type is a static impl Trait. + /// Print the error message for lifetime errors when the return type is a static `impl Trait`, + /// `dyn Trait` or if a method call on a trait object introduces a static requirement. pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); let tcx = self.tcx(); @@ -34,8 +36,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sub_r, sup_r, ) if **sub_r == RegionKind::ReStatic => { - // This is for the implicit `'static` requirement coming from `impl dyn Trait {}`. - if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { let param = self.find_param_with_region(sup_r, sub_r)?; let lifetime = if sup_r.has_name() { format!("lifetime `{}`", sup_r) @@ -55,7 +57,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .map(|s| format!("`{}`", s)) .unwrap_or_else(|| "`fn` parameter".to_string()), lifetime, - assoc.ident, + ctxt.assoc_item.ident, ); err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); err.span_label( @@ -63,7 +65,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { &format!( "...is captured and required to live as long as `'static` here \ because of an implicit lifetime bound on the {}", - match assoc.container { + match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => format!("`impl` of `{}`", tcx.def_path_str(id)), AssocItemContainer::ImplContainer(_) => @@ -71,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }, ), ); - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { err.emit(); return Some(ErrorReported); } else { @@ -117,25 +119,26 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut postfix = String::new(); if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) && fn_returns.is_empty() { err.code(rustc_errors::error_code!(E0767)); err.set_primary_message(&format!( "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ requirement", - param_name, lifetime, assoc.ident, + param_name, lifetime, ctxt.assoc_item.ident, )); postfix = format!( " because of an implicit lifetime on the {}", - match assoc.container { + match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => format!("`impl` of `{}`", tcx.def_path_str(id)), AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), }, ); } + // } } } @@ -316,128 +319,104 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default - /// `'static` obligation. Find `impl` blocks that are implemented + /// `'static` obligation. Suggest relaxing that implicit bound. fn find_impl_on_dyn_trait( &self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, - assoc: &AssocItem, + ctxt: &UnifyReceiverContext<'tcx>, ) -> bool { let tcx = self.tcx(); let mut suggested = false; - // Find the trait object types in the argument. - let mut v = TraitObjectVisitor(vec![]); - v.visit_ty(ty); - - let container_id = match assoc.container { - // When the obligation comes from an `impl Foo for dyn Bar {}`, we - // have the `DefId` of the `trait` itself, not the relevant `impl` - // block. Because of this, we have to look at all the `trait`s - // available, and filter out all that are not of `Foo` (this `def_id`) - // and not of `Bar` (the `filter_map` later in this method). - AssocItemContainer::TraitContainer(def_id) => def_id, + // Find the method being called. + let instance = match ty::Instance::resolve( + tcx, + ctxt.param_env, + ctxt.assoc_item.def_id, + self.infcx.resolve_vars_if_possible(&ctxt.substs), + ) { + Ok(Some(instance)) => instance, + _ => return false, + }; - // When the obligation comes from an `impl dyn Trait {}`, we already - // have the `DefId` of the relevant `Item`, so we use it directly. - AssocItemContainer::ImplContainer(def_id) => { - if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = - tcx.hir().get_if_local(def_id) - { - for found_did in &v.0 { - let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); - hir_v.visit_ty(self_ty); - if let [span] = &hir_v.0[..] { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label( - *span, - "this has an implicit `'static` lifetime requirement".to_string(), - ); - multi_span.push_span_label( - assoc.ident.span, - "`'static` requirement is introduced when calling this method" - .to_string(), - ); - err.span_note( - multi_span, - &format!( - "`{}`'s inherent `impl` has a `'static` requirement", - tcx.def_path_str(*found_did), - ), - ); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } + // Get the `Ident` of the method being called and the corresponding `impl` (to point at + // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). + let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) { + Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => { + match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) { + Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => { + (ident, self_ty) } + _ => return false, } - return suggested; } - }; - - // Find all the `impl`s in the local scope that can be called on the type parameter. And - // retain all that are `impl`s of the trait that originated the `'static` obligation. - // This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above. - let impl_self_tys = tcx - .all_traits(LOCAL_CRATE) - .iter() - .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did)) - .filter_map(|impl_node| { - let impl_did = tcx.hir().local_def_id(*impl_node); - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), items, .. }, - .. - })) if of_trait.trait_def_id() == Some(container_id) => Some(( - self_ty, - // Get the ident of the method, in order to use its `Span`. - items + Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => { + let parent_id = tcx.hir().get_parent_item(*hir_id); + match tcx.hir().find(parent_id) { + Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { + // The method being called is defined in the `trait`, but the `'static` + // obligation comes from the `impl`. Find that `impl` so that we can point + // at it in the suggestion. + let trait_did = tcx.hir().local_def_id(parent_id).to_def_id(); + match tcx.hir().trait_impls(trait_did) .iter() - .filter(|item| item.ident == assoc.ident) - .map(|item| item.ident) + .filter_map(|impl_node| { + let impl_did = tcx.hir().local_def_id(*impl_node); + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. }, + .. + })) if of_trait.trait_def_id() == Some(trait_did) => Some(self_ty), + _ => None, + } + }) .next() - .unwrap_or(assoc.ident), - )), - _ => None, + { + Some(self_ty) => (ident, self_ty), + _ => return false, + } + } + _ => return false, } - }); + } + _ => return false, + }; - // Given all the `impl`s of the relevant `trait`, look for those that are implemented for - // the trait object in the `fn` parameter type. - for (self_ty, method) in impl_self_tys { - for found_did in &v.0 { - let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); - hir_v.visit_ty(self_ty); - if let [span] = &hir_v.0[..] { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label( - *span, - "this has an implicit `'static` lifetime requirement".to_string(), - ); - multi_span.push_span_label( - method.span, - "`'static` requirement is introduced when calling this method".to_string(), - ); - err.span_note( - multi_span, - &format!( - "`{}`'s `impl` of `{}` has an implicit `'static` requirement", - tcx.def_path_str(*found_did), - tcx.def_path_str(container_id), - ), - ); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } + // Find the trait object types in the argument, so we point at *only* the trait object. + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + for found_did in &v.0 { + let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + hir_v.visit_ty(self_ty); + for span in &hir_v.0 { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this has an implicit `'static` lifetime requirement".to_string(), + ); + multi_span.push_span_label( + ident.span, + "calling this method introduces the `impl`'s 'static` requirement".to_string(), + ); + err.span_note( + multi_span, + &format!( + "{} has a `'static` requirement", + match ctxt.assoc_item.container { + AssocItemContainer::TraitContainer(id) => + format!("`impl` of `{}`", tcx.def_path_str(id)), + AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), + }, + ), + ); + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; } } suggested diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index c066ea831b298..d2747e5fc659b 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -169,6 +169,13 @@ impl<'tcx> ObligationCause<'tcx> { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct UnifyReceiverContext<'tcx> { + pub assoc_item: ty::AssocItem, + pub param_env: ty::ParamEnv<'tcx>, + pub substs: SubstsRef<'tcx>, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from the span. @@ -300,7 +307,7 @@ pub enum ObligationCauseCode<'tcx> { /// Method receiver MethodReceiver, - UnifyReceiver(Rc), + UnifyReceiver(Box>), /// `return` with no expression ReturnNoExpression, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 61ef0821733e8..18b4371053a89 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -213,13 +213,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::StartFunctionType => Some(super::StartFunctionType), super::IntrinsicType => Some(super::IntrinsicType), super::MethodReceiver => Some(super::MethodReceiver), - super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())), + super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), } } } +impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> { + type Lifted = traits::UnifyReceiverContext<'tcx>; + fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { + tcx.lift(&self.param_env).and_then(|param_env| { + tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext { + assoc_item: self.assoc_item, + param_env, + substs, + }) + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> { type Lifted = traits::DerivedObligationCause<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs index cf575d3eca9c2..dd7ea55cc1043 100644 --- a/src/librustc_trait_selection/traits/codegen/mod.rs +++ b/src/librustc_trait_selection/traits/codegen/mod.rs @@ -6,6 +6,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, + Unimplemented, }; use rustc_errors::ErrorReported; use rustc_middle::ty::fold::TypeFoldable; @@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>( ); return Err(ErrorReported); } + 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. + infcx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + &format!( + "Encountered error `Unimplemented` selecting `{:?}` during codegen", + trait_ref + ), + ); + return Err(ErrorReported); + } Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index e94b44d879533..0632ce2319aee 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1706,7 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression - | ObligationCauseCode::UnifyReceiver(_) + | ObligationCauseCode::UnifyReceiver(..) | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 58cbe8b2479d6..ed84095ae6b0c 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -6,7 +6,7 @@ use crate::hir::def_id::DefId; use crate::hir::GenericArg; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; -use rustc_middle::traits::ObligationCauseCode; +use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; @@ -16,7 +16,6 @@ use rustc_span::Span; use rustc_trait_selection::traits; use std::ops::Deref; -use std::rc::Rc; struct ConfirmContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -97,7 +96,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", self_ty, method_sig_rcvr, method_sig, method_predicates ); - self.unify_receivers(self_ty, method_sig_rcvr, &pick); + self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); @@ -345,12 +344,20 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, + substs: SubstsRef<'tcx>, ) { debug!( "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}", self_ty, method_self_ty, self.span, pick ); - let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item))); + let cause = self.cause( + self.span, + ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext { + assoc_item: pick.item, + param_env: self.param_env, + substs, + })), + ); match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index 832b185e619fa..45e6cfdb82131 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -5,19 +5,19 @@ mod foo { trait OtherTrait<'a> {} impl<'a> OtherTrait<'a> for &'a () {} - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait + '_ { - fn use_self(&self) -> &() { panic!() } + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } } - impl Irrelevant for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0759 + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 } } @@ -76,13 +76,11 @@ mod ban { trait ObjectTrait {} trait MyTrait { - fn use_self(&self) -> &(); + fn use_self(&self) -> &() { panic!() } } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait + '_ { - fn use_self(&self) -> &() { panic!() } - } + impl MyTrait for dyn ObjectTrait + '_ {} impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { @@ -90,5 +88,4 @@ mod ban { } } - fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index 8765591c4a114..fb6e62e76da88 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -1,10 +1,10 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body -LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self::() + | ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here | = help: consider replacing `'a` with `'static` @@ -19,7 +19,7 @@ LL | val.use_self() = help: consider replacing `'a` with `'static` error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | --- `val` is a reference that is only valid in the function body diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index ba26c2d67dfa8..7de11f4f8fc51 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -5,19 +5,19 @@ mod foo { trait OtherTrait<'a> {} impl<'a> OtherTrait<'a> for &'a () {} - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } } - impl Irrelevant for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0759 + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 } } @@ -76,13 +76,11 @@ mod ban { trait ObjectTrait {} trait MyTrait { - fn use_self(&self) -> &(); + fn use_self(&self) -> &() { panic!() } } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } - } + impl MyTrait for dyn ObjectTrait {} impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { @@ -90,5 +88,4 @@ mod ban { } } - fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 425159edbcd4a..1375ac8db8ded 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -1,22 +1,22 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13 | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | ------------------- this data with lifetime `'a`... -LL | val.use_self() +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ---------------------- this data with lifetime `'a`... +LL | val.use_self::() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `foo::ObjectTrait`'s `impl` of `foo::MyTrait` has an implicit `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26 +note: `impl` of `foo::MyTrait` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32 | -LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | -LL | impl MyTrait for dyn ObjectTrait + '_ { - | ^^^^ +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 @@ -26,36 +26,37 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl` | -note: `bat::ObjectTrait`'s inherent `impl` has a `'static` requirement +note: inherent `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 | LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { | ^^^^ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | ------------------- this data with lifetime `'a`... LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `ban::ObjectTrait`'s `impl` of `ban::MyTrait` has an implicit `'static` requirement +note: `impl` of `ban::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26 | -LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement help: consider relaxing the implicit `'static` requirement | -LL | impl MyTrait for dyn ObjectTrait + '_ { +LL | impl MyTrait for dyn ObjectTrait + '_ {} | ^^^^ help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound | @@ -70,13 +71,13 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait` | -note: `bar::ObjectTrait`'s `impl` of `bar::MyTrait` has an implicit `'static` requirement +note: `impl` of `bar::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 | LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { @@ -90,13 +91,13 @@ LL | fn use_it<'a>(val: &'a Box) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait` | -note: `baz::ObjectTrait`'s `impl` of `baz::MyTrait` has an implicit `'static` requirement +note: `impl` of `baz::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 | LL | impl MyTrait for Box { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for Box { From 3712dfc677bb5dff909cdc29fd2da11772ddba9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 1 Jul 2020 00:24:55 -0700 Subject: [PATCH 18/22] Partially account for case where used method is from trait --- .../nice_region_error/static_impl_trait.rs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9c2e02968f607..18466b00da971 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -340,6 +340,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { _ => return false, }; + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + // Get the `Ident` of the method being called and the corresponding `impl` (to point at // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) { @@ -359,15 +362,30 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // obligation comes from the `impl`. Find that `impl` so that we can point // at it in the suggestion. let trait_did = tcx.hir().local_def_id(parent_id).to_def_id(); - match tcx.hir().trait_impls(trait_did) + match tcx + .hir() + .trait_impls(trait_did) .iter() .filter_map(|impl_node| { let impl_did = tcx.hir().local_def_id(*impl_node); match tcx.hir().get_if_local(impl_did.to_def_id()) { Some(Node::Item(Item { - kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. }, + kind: ItemKind::Impl { self_ty, .. }, .. - })) if of_trait.trait_def_id() == Some(trait_did) => Some(self_ty), + })) if v.0.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut hir_v = HirTraitObjectVisitor(vec![], *did); + hir_v.visit_ty(self_ty); + !hir_v.0.is_empty() + }) => + { + Some(self_ty) + } _ => None, } }) @@ -384,8 +402,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; // Find the trait object types in the argument, so we point at *only* the trait object. - let mut v = TraitObjectVisitor(vec![]); - v.visit_ty(ty); for found_did in &v.0 { let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); hir_v.visit_ty(self_ty); From 53d96b5159ee4eb937728bbc33c28c3b98ebebd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 1 Jul 2020 14:02:57 -0700 Subject: [PATCH 19/22] Handle fully-qualified paths and add test cases --- .../nice_region_error/static_impl_trait.rs | 184 ++++++++++-------- ...-bound-needing-more-suggestions.nll.stderr | 37 ++++ ...t-static-bound-needing-more-suggestions.rs | 114 +++++++++++ ...atic-bound-needing-more-suggestions.stderr | 57 ++++++ ...dyn-trait-with-implicit-static-bound.fixed | 25 ++- ...rait-with-implicit-static-bound.nll.stderr | 14 +- ...on-dyn-trait-with-implicit-static-bound.rs | 25 ++- ...yn-trait-with-implicit-static-bound.stderr | 46 ++++- 8 files changed, 404 insertions(+), 98 deletions(-) create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 18466b00da971..9581ee611fce8 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -12,6 +12,7 @@ use rustc_hir::{ TyKind, }; use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; +use rustc_span::symbol::Ident; use rustc_span::{MultiSpan, Span}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -115,33 +116,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); debug!("try_report_static_impl_trait: param_info={:?}", param); - let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); - - let mut postfix = String::new(); - if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) - && fn_returns.is_empty() - { - err.code(rustc_errors::error_code!(E0767)); - err.set_primary_message(&format!( - "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ - requirement", - param_name, lifetime, ctxt.assoc_item.ident, - )); - postfix = format!( - " because of an implicit lifetime on the {}", - match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer(id) => - format!("`impl` of `{}`", tcx.def_path_str(id)), - AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), - }, - ); - } - // } - } - } - // We try to make the output have fewer overlapping spans if possible. if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) && sup_origin.span() != return_sp @@ -168,35 +142,68 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | ---- ^ err.span_label( sup_origin.span(), - &format!( - "...is captured here, requiring it to live as long as `'static`{}", - postfix - ), + "...is captured here, requiring it to live as long as `'static`", ); } else { err.span_label(sup_origin.span(), "...is captured here..."); if return_sp < sup_origin.span() { err.span_note( return_sp, - &format!("...and is required to live as long as `'static` here{}", postfix), + "...and is required to live as long as `'static` here", ); } else { err.span_label( return_sp, - &format!("...and is required to live as long as `'static` here{}", postfix), + "...and is required to live as long as `'static` here", ); } } } else { err.span_label( return_sp, - &format!( - "...is captured and required to live as long as `'static` here{}", - postfix - ), + "...is captured and required to live as long as `'static` here", ); } + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); + + let mut override_error_code = None; + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a + // `'static` lifetime when called as a method on a binding: `bar.qux()`. + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { + override_error_code = Some(ctxt.assoc_item.ident); + } + } + } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { + if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code { + // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` + // lifetime as above, but called using a fully-qualified path to the method: + // `Foo::qux(bar)`. + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(param.param_ty); + if let Some((ident, self_ty)) = + self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..]) + { + if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty) + { + override_error_code = Some(ident); + } + } + } + } + if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { + // Provide a more targetted error code and description. + err.code(rustc_errors::error_code!(E0767)); + err.set_primary_message(&format!( + "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ + requirement", + param_name, lifetime, ident, + )); + } + debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` let consider = "consider changing the"; @@ -318,40 +325,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(ErrorReported) } - /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default - /// `'static` obligation. Suggest relaxing that implicit bound. - fn find_impl_on_dyn_trait( + fn get_impl_ident_and_self_ty_from_trait( &self, - err: &mut DiagnosticBuilder<'_>, - ty: Ty<'_>, - ctxt: &UnifyReceiverContext<'tcx>, - ) -> bool { + def_id: DefId, + trait_objects: &[DefId], + ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.tcx(); - let mut suggested = false; - - // Find the method being called. - let instance = match ty::Instance::resolve( - tcx, - ctxt.param_env, - ctxt.assoc_item.def_id, - self.infcx.resolve_vars_if_possible(&ctxt.substs), - ) { - Ok(Some(instance)) => instance, - _ => return false, - }; - - let mut v = TraitObjectVisitor(vec![]); - v.visit_ty(ty); - - // Get the `Ident` of the method being called and the corresponding `impl` (to point at - // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). - let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) { + match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => { match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) { Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => { - (ident, self_ty) + Some((*ident, self_ty)) } - _ => return false, + _ => None, } } Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => { @@ -372,7 +358,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. - })) if v.0.iter().all(|did| { + })) if trait_objects.iter().all(|did| { // FIXME: we should check `self_ty` against the receiver // type in the `UnifyReceiver` context, but for now, use // this imperfect proxy. This will fail if there are @@ -391,20 +377,64 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) .next() { - Some(self_ty) => (ident, self_ty), - _ => return false, + Some(self_ty) => Some((*ident, self_ty)), + _ => None, } } - _ => return false, + _ => None, } } + _ => None, + } + } + + /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default + /// `'static` obligation. Suggest relaxing that implicit bound. + fn find_impl_on_dyn_trait( + &self, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + ctxt: &UnifyReceiverContext<'tcx>, + ) -> bool { + let tcx = self.tcx(); + + // Find the method being called. + let instance = match ty::Instance::resolve( + tcx, + ctxt.param_env, + ctxt.assoc_item.def_id, + self.infcx.resolve_vars_if_possible(&ctxt.substs), + ) { + Ok(Some(instance)) => instance, _ => return false, }; + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + + // Get the `Ident` of the method being called and the corresponding `impl` (to point at + // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). + let (ident, self_ty) = + match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) { + Some((ident, self_ty)) => (ident, self_ty), + None => return false, + }; + // Find the trait object types in the argument, so we point at *only* the trait object. - for found_did in &v.0 { + self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty) + } + + fn suggest_constrain_dyn_trait_in_impl( + &self, + err: &mut DiagnosticBuilder<'_>, + found_dids: &[DefId], + ident: Ident, + self_ty: &hir::Ty<'_>, + ) -> bool { + let mut suggested = false; + for found_did in found_dids { let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); - hir_v.visit_ty(self_ty); + hir_v.visit_ty(&self_ty); for span in &hir_v.0 { let mut multi_span: MultiSpan = vec![*span].into(); multi_span.push_span_label( @@ -415,17 +445,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ident.span, "calling this method introduces the `impl`'s 'static` requirement".to_string(), ); - err.span_note( - multi_span, - &format!( - "{} has a `'static` requirement", - match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer(id) => - format!("`impl` of `{}`", tcx.def_path_str(id)), - AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), - }, - ), - ); + err.span_note(multi_span, "the used `impl` has a `'static` requirement"); err.span_suggestion_verbose( span.shrink_to_hi(), "consider relaxing the implicit `'static` requirement", diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr new file mode 100644 index 0000000000000..6921926590a69 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr @@ -0,0 +1,37 @@ +error[E0597]: `val` does not live long enough + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9 + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` +LL | val.use_self() + | ^^^ borrowed value does not live long enough +LL | } + | - `val` dropped here while still borrowed + | +help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs new file mode 100644 index 0000000000000..ae6ffa8d93e01 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -0,0 +1,114 @@ + +// FIXME: the following cases need to suggest more things to make users reach a working end state. + +mod bav { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR E0597 + } +} + +mod bap { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0515 + } +} + +// This case in particular requires the user to write all of the bounds we have in `mod bax`. +mod bay { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() //~ ERROR E0767 + } +} + +mod bax { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait<'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + trait Bar {} + + impl<'a> MyTrait<'a> for Box + 'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() + } +} + +mod baw { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl<'a> MyTrait for Box>> { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: Box>>) -> impl OtherTrait<'a> + 'a{ + val.use_self() //~ ERROR E0515 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr new file mode 100644 index 0000000000000..2fab02fd1be45 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -0,0 +1,57 @@ +error[E0597]: `val` does not live long enough + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9 + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` +LL | val.use_self() + | ^^^ borrowed value does not live long enough +LL | } + | - `val` dropped here while still borrowed + | +help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` + | +LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + | ^^^^ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:67:13 + | +LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { + | -------------------------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:61:30 + | +LL | impl MyTrait for Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box + '_> { + | ^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index 45e6cfdb82131..c568738d94b45 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -78,14 +78,35 @@ mod ban { trait MyTrait { fn use_self(&self) -> &() { panic!() } } - trait Irrelevant {} + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } impl MyTrait for dyn ObjectTrait + '_ {} - impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { val.use_self() //~ ERROR E0759 } } +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR E0759 + } +} + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index fb6e62e76da88..697467dc3a630 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -19,7 +19,7 @@ LL | val.use_self() = help: consider replacing `'a` with `'static` error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | --- `val` is a reference that is only valid in the function body @@ -28,5 +28,15 @@ LL | val.use_self() | = help: consider replacing `'a` with `'static` -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here + | + = help: consider replacing `'a` with `'static` + +error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index 7de11f4f8fc51..8dd1e5d78de09 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -78,14 +78,35 @@ mod ban { trait MyTrait { fn use_self(&self) -> &() { panic!() } } - trait Irrelevant {} + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } impl MyTrait for dyn ObjectTrait {} - impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { val.use_self() //~ ERROR E0759 } } +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR E0759 + } +} + fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 1375ac8db8ded..7e814fc664625 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -6,7 +6,7 @@ LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + LL | val.use_self::() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `impl` of `foo::MyTrait` has a `'static` requirement +note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32 | LL | impl MyTrait for dyn ObjectTrait { @@ -26,7 +26,7 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl` | -note: inherent `impl` has a `'static` requirement +note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 | LL | impl dyn ObjectTrait { @@ -39,15 +39,15 @@ LL | impl dyn ObjectTrait + '_ { | ^^^^ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | ------------------- this data with lifetime `'a`... LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `impl` of `ban::MyTrait` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26 +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s 'static` requirement @@ -63,15 +63,41 @@ help: to declare that the `impl Trait` captures data from argument `val`, you ca LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | ^^^^ +error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:27 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ------------------- this data with lifetime `'a`... +LL | MyTrait::use_self(val) + | ^^^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 + | +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^ +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:104:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^ + error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { | ------------------- this data with lifetime `'a`... LL | val.use_self() - | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait` + | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `impl` of `bar::MyTrait` has a `'static` requirement +note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 | LL | impl MyTrait for dyn ObjectTrait { @@ -89,9 +115,9 @@ error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an impli LL | fn use_it<'a>(val: &'a Box) -> &'a () { | ----------------------------- this data with lifetime `'a`... LL | val.use_self() - | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait` + | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `impl` of `baz::MyTrait` has a `'static` requirement +note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 | LL | impl MyTrait for Box { @@ -103,6 +129,6 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for Box { | ^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0759`. From ed53de029cf84651423007ec68305d6e772c819f Mon Sep 17 00:00:00 2001 From: Dennis Hamester Date: Sat, 11 Jul 2020 19:39:02 +0200 Subject: [PATCH 20/22] rustdoc: Always warn when linking from public to private items Change the logic such that linking from a public to a private item always triggers intra_doc_link_resolution_failure. Previously, the warning was not emitted when --document-private-items is passed. Also don't rely anymore on the item's visibility, which would falsely trigger the lint now that the check for --document-private-items is gone. --- .../passes/collect_intra_doc_links.rs | 17 ++++++++++++----- .../intra-links-private.private.stderr | 10 ++++++++++ .../intra-links-private.public.stderr | 2 +- src/test/rustdoc-ui/intra-links-private.rs | 3 +-- src/test/rustdoc-ui/issue-74134.private.stderr | 10 ++++++++++ src/test/rustdoc-ui/issue-74134.rs | 4 ++-- 6 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 src/test/rustdoc-ui/intra-links-private.private.stderr create mode 100644 src/test/rustdoc-ui/issue-74134.private.stderr diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 6f221da1168c6..8e113cfa563c8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -790,13 +790,20 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { item.attrs.links.push((ori_link, None, fragment)); } else { debug!("intra-doc link to {} resolved to {:?}", path_str, res); - if let Some(local) = res.opt_def_id().and_then(|def_id| def_id.as_local()) { + + // item can be non-local e.g. when using #[doc(primitive = "pointer")] + if let Some((src_id, dst_id)) = res + .opt_def_id() + .and_then(|def_id| def_id.as_local()) + .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id))) + { use rustc_hir::def_id::LOCAL_CRATE; - let hir_id = self.cx.tcx.hir().as_local_hir_id(local); - if !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_id) - && (item.visibility == Visibility::Public) - && !self.cx.render_options.document_private + let hir_src = self.cx.tcx.hir().as_local_hir_id(src_id); + let hir_dst = self.cx.tcx.hir().as_local_hir_id(dst_id); + + if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src) + && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst) { privacy_error(cx, &item, &path_str, &dox, link_range); continue; diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-links-private.private.stderr new file mode 100644 index 0000000000000..6a23afb0798a9 --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-private.private.stderr @@ -0,0 +1,10 @@ +warning: public documentation for `DocMe` links to private item `DontDocMe` + --> $DIR/intra-links-private.rs:5:11 + | +LL | /// docs [DontDocMe] + | ^^^^^^^^^ this item is private + | + = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr index a124435b08a99..6a23afb0798a9 100644 --- a/src/test/rustdoc-ui/intra-links-private.public.stderr +++ b/src/test/rustdoc-ui/intra-links-private.public.stderr @@ -1,5 +1,5 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` - --> $DIR/intra-links-private.rs:6:11 + --> $DIR/intra-links-private.rs:5:11 | LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private diff --git a/src/test/rustdoc-ui/intra-links-private.rs b/src/test/rustdoc-ui/intra-links-private.rs index 1b97f6e61bd23..613236d75d2ee 100644 --- a/src/test/rustdoc-ui/intra-links-private.rs +++ b/src/test/rustdoc-ui/intra-links-private.rs @@ -1,10 +1,9 @@ // check-pass // revisions: public private // [private]compile-flags: --document-private-items -#![cfg_attr(private, deny(intra_doc_link_resolution_failure))] /// docs [DontDocMe] -//[public]~^ WARNING public documentation for `DocMe` links to private item `DontDocMe` +//~^ WARNING public documentation for `DocMe` links to private item `DontDocMe` // FIXME: for [private] we should also make sure the link was actually generated pub struct DocMe; struct DontDocMe; diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr new file mode 100644 index 0000000000000..3c41f7e63e637 --- /dev/null +++ b/src/test/rustdoc-ui/issue-74134.private.stderr @@ -0,0 +1,10 @@ +warning: public documentation for `public_item` links to private item `PrivateType` + --> $DIR/issue-74134.rs:19:10 + | +LL | /// [`PrivateType`] + | ^^^^^^^^^^^^^ this item is private + | + = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/rustdoc-ui/issue-74134.rs b/src/test/rustdoc-ui/issue-74134.rs index fe484b43fb6fc..b1be9123aaf83 100644 --- a/src/test/rustdoc-ui/issue-74134.rs +++ b/src/test/rustdoc-ui/issue-74134.rs @@ -4,7 +4,7 @@ // There are 4 cases here: // 1. public item -> public type: no warning -// 2. public item -> private type: warning, if --document-private-items is not passed +// 2. public item -> private type: warning // 3. private item -> public type: no warning // 4. private item -> private type: no warning // All 4 cases are tested with and without --document-private-items. @@ -17,7 +17,7 @@ pub struct PublicType; pub struct Public { /// [`PublicType`] /// [`PrivateType`] - //[public]~^ WARNING public documentation for `public_item` links to private item `PrivateType` + //~^ WARNING public documentation for `public_item` links to private item `PrivateType` pub public_item: u32, /// [`PublicType`] From c14641a814696f6dffe5a0e7d693af31a4e40d09 Mon Sep 17 00:00:00 2001 From: Dennis Hamester Date: Wed, 22 Jul 2020 19:53:43 +0200 Subject: [PATCH 21/22] rustdoc: Add explanation when linting against public to private item links The additional note helps explaining why the lint was triggered and that --document-private-items directly influences the link resolution. --- src/librustdoc/passes/collect_intra_doc_links.rs | 7 +++++++ src/test/rustdoc-ui/intra-links-private.private.stderr | 1 + src/test/rustdoc-ui/intra-links-private.public.stderr | 1 + src/test/rustdoc-ui/issue-74134.private.stderr | 1 + src/test/rustdoc-ui/issue-74134.public.stderr | 1 + 5 files changed, 11 insertions(+) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8e113cfa563c8..5187839423d6b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1076,6 +1076,13 @@ fn privacy_error( if let Some(sp) = sp { diag.span_label(sp, "this item is private"); } + + let note_msg = if cx.render_options.document_private { + "this link resolves only because you passed `--document-private-items`, but will break without" + } else { + "this link will resolve properly if you pass `--document-private-items`" + }; + diag.note(note_msg); }); } diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-links-private.private.stderr index 6a23afb0798a9..a2148b82f819a 100644 --- a/src/test/rustdoc-ui/intra-links-private.private.stderr +++ b/src/test/rustdoc-ui/intra-links-private.private.stderr @@ -5,6 +5,7 @@ LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + = note: this link resolves only because you passed `--document-private-items`, but will break without warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr index 6a23afb0798a9..56742406992fc 100644 --- a/src/test/rustdoc-ui/intra-links-private.public.stderr +++ b/src/test/rustdoc-ui/intra-links-private.public.stderr @@ -5,6 +5,7 @@ LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + = note: this link will resolve properly if you pass `--document-private-items` warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr index 3c41f7e63e637..9c5cdf0117cab 100644 --- a/src/test/rustdoc-ui/issue-74134.private.stderr +++ b/src/test/rustdoc-ui/issue-74134.private.stderr @@ -5,6 +5,7 @@ LL | /// [`PrivateType`] | ^^^^^^^^^^^^^ this item is private | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + = note: this link resolves only because you passed `--document-private-items`, but will break without warning: 1 warning emitted diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr index 3c41f7e63e637..ff2951d864e64 100644 --- a/src/test/rustdoc-ui/issue-74134.public.stderr +++ b/src/test/rustdoc-ui/issue-74134.public.stderr @@ -5,6 +5,7 @@ LL | /// [`PrivateType`] | ^^^^^^^^^^^^^ this item is private | = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + = note: this link will resolve properly if you pass `--document-private-items` warning: 1 warning emitted From 889a4d9a0baf06497106eb705143e379c180bd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 20 Jul 2020 13:56:50 -0700 Subject: [PATCH 22/22] Change error code number --- src/librustc_error_codes/error_codes.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 4 ++-- ...-static-bound-needing-more-suggestions.nll.stderr | 6 +++--- ...implicit-static-bound-needing-more-suggestions.rs | 3 +-- ...icit-static-bound-needing-more-suggestions.stderr | 12 ++++++------ ...mpl-on-dyn-trait-with-implicit-static-bound.fixed | 6 +++--- .../impl-on-dyn-trait-with-implicit-static-bound.rs | 6 +++--- ...pl-on-dyn-trait-with-implicit-static-bound.stderr | 6 +++--- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 7c762a3415e13..72302962d8603 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -633,5 +633,5 @@ E0771: include_str!("./error_codes/E0771.md"), E0755, // `#[ffi_pure]` is only allowed on foreign functions E0756, // `#[ffi_const]` is only allowed on foreign functions E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]` - E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. + E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9581ee611fce8..4fa6d9d239424 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut err = struct_span_err!( tcx.sess, cause.span, - E0767, + E0772, "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ requirement", param @@ -196,7 +196,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { // Provide a more targetted error code and description. - err.code(rustc_errors::error_code!(E0767)); + err.code(rustc_errors::error_code!(E0772)); err.set_primary_message(&format!( "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ requirement", diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr index 6921926590a69..acf0c0ece4020 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr @@ -1,5 +1,5 @@ error[E0597]: `val` does not live long enough - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 | LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` @@ -14,7 +14,7 @@ LL | fn use_it<'a>(val: Box>) -> impl OtherTrai | ^^^^ error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | val.use_self() | `val` is borrowed here error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 | LL | val.use_self() | ---^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index ae6ffa8d93e01..b2dc16a27e310 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -1,4 +1,3 @@ - // FIXME: the following cases need to suggest more things to make users reach a working end state. mod bav { @@ -64,7 +63,7 @@ mod bay { impl Bar for i32 {} fn use_it<'a>(val: Box + 'a>) -> &'a () { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index 2fab02fd1be45..00971b41c7ce6 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -1,5 +1,5 @@ error[E0597]: `val` does not live long enough - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 | LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` @@ -14,7 +14,7 @@ LL | fn use_it<'a>(val: Box>) -> impl OtherTrai | ^^^^ error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | val.use_self() | `val` is borrowed here error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -31,8 +31,8 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here -error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:67:13 +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:13 | LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { | -------------------------------------- this data with lifetime `'a`... @@ -40,7 +40,7 @@ LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:61:30 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 | LL | impl MyTrait for Box> { | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index c568738d94b45..3c10f85d9423a 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -34,7 +34,7 @@ mod bar { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } @@ -51,7 +51,7 @@ mod baz { impl Irrelevant for Box {} fn use_it<'a>(val: &'a Box) -> &'a () { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } @@ -66,7 +66,7 @@ mod bat { } fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index 8dd1e5d78de09..88ab03dfc1ef1 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -34,7 +34,7 @@ mod bar { impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } @@ -51,7 +51,7 @@ mod baz { impl Irrelevant for Box {} fn use_it<'a>(val: &'a Box) -> &'a () { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } @@ -66,7 +66,7 @@ mod bat { } fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0767 + val.use_self() //~ ERROR E0772 } } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 7e814fc664625..2fb6c25fd1702 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -18,7 +18,7 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { @@ -89,7 +89,7 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ {} | ^^^^ -error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { @@ -109,7 +109,7 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement +error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13 | LL | fn use_it<'a>(val: &'a Box) -> &'a () {