mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Enforce supertrait outlives obligations hold when confirming impl
This commit is contained in:
parent
9179d9b334
commit
6a891ec4fe
@ -87,6 +87,19 @@ where
|
|||||||
.map(|pred| goal.with(cx, pred));
|
.map(|pred| goal.with(cx, pred));
|
||||||
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
||||||
|
|
||||||
|
// We currently elaborate all supertrait obligations from impls. This
|
||||||
|
// can be removed when we actually do coinduction correctly and just
|
||||||
|
// register that the impl header must be WF.
|
||||||
|
let goal_clause: I::Clause = goal.predicate.upcast(cx);
|
||||||
|
for clause in elaborate::elaborate(cx, [goal_clause]) {
|
||||||
|
if matches!(
|
||||||
|
clause.kind().skip_binder(),
|
||||||
|
ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..)
|
||||||
|
) {
|
||||||
|
ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)
|
ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use std::fmt::{self, Display};
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::{cmp, iter};
|
use std::{cmp, iter};
|
||||||
|
|
||||||
|
use hir::def::DefKind;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_errors::{Diag, EmissionGuarantee};
|
use rustc_errors::{Diag, EmissionGuarantee};
|
||||||
@ -14,8 +15,9 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_infer::infer::relate::TypeRelation;
|
use rustc_infer::infer::relate::TypeRelation;
|
||||||
use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
|
use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType};
|
||||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
|
use rustc_infer::traits::util::elaborate;
|
||||||
use rustc_infer::traits::TraitObligation;
|
use rustc_infer::traits::TraitObligation;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex};
|
use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex};
|
||||||
@ -2798,6 +2800,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).upcast(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
|
obligations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,6 +451,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
|
|||||||
+ UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
|
+ UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
|
||||||
+ UpcastFrom<I, ty::TraitRef<I>>
|
+ UpcastFrom<I, ty::TraitRef<I>>
|
||||||
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
|
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
|
||||||
|
+ UpcastFrom<I, ty::TraitPredicate<I>>
|
||||||
|
+ UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
|
||||||
+ UpcastFrom<I, ty::ProjectionPredicate<I>>
|
+ UpcastFrom<I, ty::ProjectionPredicate<I>>
|
||||||
+ UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
|
+ UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
|
||||||
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
|
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
|
||||||
|
@ -5,6 +5,7 @@ trait Trait<'a>: 'a {
|
|||||||
// if the `T: 'a` bound gets implied we would probably get ub here again
|
// if the `T: 'a` bound gets implied we would probably get ub here again
|
||||||
impl<'a, T> Trait<'a> for T {
|
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
|
||||||
|
//~| ERROR the parameter type `T` may not live long enough
|
||||||
type Type = ();
|
type Type = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,21 @@ help: consider adding an explicit lifetime bound
|
|||||||
LL | impl<'a, T: 'a> Trait<'a> for T {
|
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
|
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!");
|
LL | let x = String::from("Hello World!");
|
||||||
| - binding `x` declared here
|
| - binding `x` declared here
|
||||||
@ -33,7 +46,7 @@ help: consider cloning the value if the performance cost is acceptable
|
|||||||
LL | let y = f(&x.clone(), ());
|
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.
|
Some errors have detailed explanations: E0309, E0505.
|
||||||
For more information about an error, try `rustc --explain E0309`.
|
For more information about an error, try `rustc --explain E0309`.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub trait Arbitrary: Sized + 'static {}
|
pub trait Arbitrary: Sized + 'static {}
|
||||||
|
|
||||||
impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
|
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() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
@ -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
|
= 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 `<Cow<'a, A> as Arbitrary>`
|
||||||
|
found `<Cow<'_, A> 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> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0478`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0478, E0495.
|
||||||
|
For more information about an error, try `rustc --explain E0478`.
|
||||||
|
12
tests/ui/wf/wf-in-where-clause-static.current.stderr
Normal file
12
tests/ui/wf/wf-in-where-clause-static.current.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/wf-in-where-clause-static.rs:18: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`.
|
12
tests/ui/wf/wf-in-where-clause-static.next.stderr
Normal file
12
tests/ui/wf/wf-in-where-clause-static.next.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/wf-in-where-clause-static.rs:18: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`.
|
@ -1,9 +1,6 @@
|
|||||||
//@ check-pass
|
//@ revisions: current next
|
||||||
//@ known-bug: #98117
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
// 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;
|
use std::fmt::Display;
|
||||||
|
|
||||||
@ -19,5 +16,6 @@ where
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let s = foo(&String::from("blah blah blah"));
|
let s = foo(&String::from("blah blah blah"));
|
||||||
|
//~^ ERROR temporary value dropped while borrowed
|
||||||
println!("{}", s);
|
println!("{}", s);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user