diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fc12fed353738..8b7f7f7bff999 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -27,6 +27,7 @@ use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; use crate::traits::Unimplemented; +use hir::def::DefKind; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; @@ -35,6 +36,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::traits::util::elaborate; use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; @@ -2795,6 +2797,34 @@ impl<'tcx> SelectionContext<'_, 'tcx> { }); } + if matches!(self.tcx().def_kind(def_id), DefKind::Impl { of_trait: true }) + && let Some(header) = self.tcx().impl_trait_header(def_id) + { + let trait_clause: ty::Clause<'tcx> = + header.trait_ref.instantiate(self.tcx(), args).to_predicate(self.tcx()); + for clause in elaborate(self.tcx(), [trait_clause]) { + if matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) + ) { + let clause = normalize_with_depth_to( + self, + param_env, + cause.clone(), + recursion_depth, + clause, + &mut obligations, + ); + obligations.push(Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate: clause.as_predicate(), + }); + } + } + } + obligations } } diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs index a7489f6fbaff4..38be3250c7d66 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs @@ -5,6 +5,7 @@ trait Trait<'a>: 'a { // if the `T: 'a` bound gets implied we would probably get ub here again impl<'a, T> Trait<'a> for T { //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough type Type = (); } diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index 382ab8636a294..11b71ff087b16 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -16,8 +16,21 @@ help: consider adding an explicit lifetime bound LL | impl<'a, T: 'a> Trait<'a> for T { | ++++ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:27 + | +LL | impl<'a, T> Trait<'a> for T { + | -- ^ ...so that the type `T` will meet its required lifetime bounds + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | impl<'a, T: 'a> Trait<'a> for T { + | ++++ + error[E0505]: cannot move out of `x` because it is borrowed - --> $DIR/implied-bounds-unnorm-associated-type-5.rs:21:10 + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:22:10 | LL | let x = String::from("Hello World!"); | - binding `x` declared here @@ -34,7 +47,7 @@ LL - let y = f(&x, ()); LL + let y = f(x.clone(), ()); | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0309, E0505. For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/static/static-lifetime.rs b/tests/ui/static/static-lifetime.rs index ce1eeb6105f09..a861a2ffedab4 100644 --- a/tests/ui/static/static-lifetime.rs +++ b/tests/ui/static/static-lifetime.rs @@ -1,6 +1,7 @@ pub trait Arbitrary: Sized + 'static {} impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound +//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a` fn main() { } diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 8c9434ce3cb0b..7a956dbfeef6e 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -11,6 +11,32 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^ = note: but lifetime parameter must outlive the static lifetime -error: aborting due to 1 previous error +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/static-lifetime.rs:3:6 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^ +note: ...so that the types are compatible + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected ` as Arbitrary>` + found ` as Arbitrary>` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0478`. +Some errors have detailed explanations: E0478, E0495. +For more information about an error, try `rustc --explain E0478`. diff --git a/tests/ui/wf/wf-in-where-clause-static.rs b/tests/ui/wf/wf-in-where-clause-static.rs index a3d360e1fb56b..097db6e7cf20d 100644 --- a/tests/ui/wf/wf-in-where-clause-static.rs +++ b/tests/ui/wf/wf-in-where-clause-static.rs @@ -1,10 +1,3 @@ -//@ check-pass -//@ known-bug: #98117 - -// Should fail. Functions are responsible for checking the well-formedness of -// their own where clauses, so this should fail and require an explicit bound -// `T: 'static`. - use std::fmt::Display; trait Static: 'static {} @@ -19,5 +12,6 @@ where fn main() { let s = foo(&String::from("blah blah blah")); + //~^ ERROR temporary value dropped while borrowed println!("{}", s); } diff --git a/tests/ui/wf/wf-in-where-clause-static.stderr b/tests/ui/wf/wf-in-where-clause-static.stderr new file mode 100644 index 0000000000000..1bbb1eede24ae --- /dev/null +++ b/tests/ui/wf/wf-in-where-clause-static.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/wf-in-where-clause-static.rs:14:18 + | +LL | let s = foo(&String::from("blah blah blah")); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`.