mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
simplify HR subtyping back to what we did before
A lot of the refactors, however, seem helpful, so leave those in, particularly since we may want to make this change in the future.
This commit is contained in:
parent
52b2db1cca
commit
75543c08c7
@ -1647,6 +1647,5 @@ register_diagnostics! {
|
||||
E0490, // a value of type `..` is borrowed for too long
|
||||
E0491, // in type `..`, reference has a longer lifetime than the data it...
|
||||
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
|
||||
E0525, // expected a closure that implements `..` but this closure only implements `..`
|
||||
E0526, // skolemization subtype
|
||||
E0525 // expected a closure that implements `..` but this closure only implements `..`
|
||||
}
|
||||
|
@ -919,17 +919,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
"");
|
||||
err
|
||||
}
|
||||
infer::SkolemizeSuccessor(span) => {
|
||||
let mut err =
|
||||
struct_span_err!(self.tcx.sess, span, E0526,
|
||||
"to satisfy higher-ranked bounds, \
|
||||
a static lifetime is required");
|
||||
self.tcx.note_and_explain_region(&mut err,
|
||||
"but the lifetime is only valid for ",
|
||||
sub,
|
||||
"");
|
||||
err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1817,11 +1806,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
"...so that references are valid when the destructor \
|
||||
runs");
|
||||
}
|
||||
infer::SkolemizeSuccessor(span) => {
|
||||
err.span_note(
|
||||
span,
|
||||
"...so that higher-ranked bounds are satisfied");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ use super::{CombinedSnapshot,
|
||||
InferCtxt,
|
||||
LateBoundRegion,
|
||||
HigherRankedType,
|
||||
SubregionOrigin,
|
||||
SkolemizationMap};
|
||||
use super::combine::CombineFields;
|
||||
use super::region_inference::{TaintDirections};
|
||||
@ -527,7 +526,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// be itself or other new variables.
|
||||
let incoming_taints = self.tainted_regions(snapshot,
|
||||
skol,
|
||||
TaintDirections::incoming());
|
||||
TaintDirections::both());
|
||||
for &tainted_region in &incoming_taints {
|
||||
// Each skolemized should only be relatable to itself
|
||||
// or new variables:
|
||||
@ -568,71 +567,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
self.issue_32330_warnings(span, &warnings);
|
||||
|
||||
for (_, &skol) in skol_map {
|
||||
// The outputs from a skolemized variable must all be
|
||||
// equatable with `'static`.
|
||||
let outgoing_taints = self.tainted_regions(snapshot,
|
||||
skol,
|
||||
TaintDirections::outgoing());
|
||||
for &tainted_region in &outgoing_taints {
|
||||
match tainted_region {
|
||||
ty::ReVar(vid) if new_vars.contains(&vid) => {
|
||||
// There is a path from a skolemized variable
|
||||
// to some region variable that doesn't escape
|
||||
// this snapshot:
|
||||
//
|
||||
// [skol] -> [tainted_region]
|
||||
//
|
||||
// We can ignore this. The reasoning relies on
|
||||
// the fact that the preivous loop
|
||||
// completed. There are two possible cases
|
||||
// here.
|
||||
//
|
||||
// - `tainted_region` eventually reaches a
|
||||
// skolemized variable, which *must* be `skol`
|
||||
// (because otherwise we would have already
|
||||
// returned `Err`). In that case,
|
||||
// `tainted_region` could be inferred to `skol`.
|
||||
//
|
||||
// - `tainted_region` never reaches a
|
||||
// skolemized variable. In that case, we can
|
||||
// safely choose `'static` as an upper bound
|
||||
// incoming edges. This is a conservative
|
||||
// choice -- the LUB might be one of the
|
||||
// incoming skolemized variables, which we
|
||||
// might know by ambient bounds. We can
|
||||
// consider a more clever choice of upper
|
||||
// bound later (modulo some theoretical
|
||||
// breakage).
|
||||
//
|
||||
// We used to force such `tainted_region` to be
|
||||
// `'static`, but that leads to problems when
|
||||
// combined with `plug_leaks`. If you have a case
|
||||
// where `[skol] -> [tainted_region] -> [skol]`,
|
||||
// then `plug_leaks` concludes it should replace
|
||||
// `'static` with a late-bound region, which is
|
||||
// clearly wrong. (Well, what actually happens is
|
||||
// you get assertion failures because it WOULD
|
||||
// have to replace 'static with a late-bound
|
||||
// region.)
|
||||
}
|
||||
ty::ReSkolemized(..) => {
|
||||
// the only skolemized region we find in the
|
||||
// successors of X can be X; if there was another
|
||||
// region Y, then X would have been in the preds
|
||||
// of Y, and we would have aborted above
|
||||
assert_eq!(skol, tainted_region);
|
||||
}
|
||||
_ => {
|
||||
self.region_vars.make_subregion(
|
||||
SubregionOrigin::SkolemizeSuccessor(span),
|
||||
ty::ReStatic,
|
||||
tainted_region);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -682,7 +616,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
skol_map
|
||||
.iter()
|
||||
.flat_map(|(&skol_br, &skol)| {
|
||||
self.tainted_regions(snapshot, skol, TaintDirections::incoming())
|
||||
self.tainted_regions(snapshot, skol, TaintDirections::both())
|
||||
.into_iter()
|
||||
.map(move |tainted_region| (tainted_region, skol_br))
|
||||
})
|
||||
|
@ -340,11 +340,6 @@ pub enum SubregionOrigin<'tcx> {
|
||||
|
||||
// Region constraint arriving from destructor safety
|
||||
SafeDestructor(Span),
|
||||
|
||||
// When doing a higher-ranked comparison, this region was a
|
||||
// successor from a skolemized region, which means that it must be
|
||||
// `'static` to be sound.
|
||||
SkolemizeSuccessor(Span),
|
||||
}
|
||||
|
||||
/// Places that type/region parameters can appear.
|
||||
@ -1798,7 +1793,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||
AddrOf(a) => a,
|
||||
AutoBorrow(a) => a,
|
||||
SafeDestructor(a) => a,
|
||||
SkolemizeSuccessor(a) => a,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt,
|
||||
base::MacEager::expr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt,
|
||||
pub fn expand_quote_item<'cx>(cx: &'cx mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[TokenTree])
|
||||
-> Box<base::MacResult+'cx> {
|
||||
|
@ -17,7 +17,7 @@ use syntax::parse::token;
|
||||
use syntax::parse::token::str_to_ident;
|
||||
use syntax::ptr::P;
|
||||
|
||||
pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||
pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||
-> Box<base::MacResult+'cx> {
|
||||
if !cx.ecfg.enable_concat_idents() {
|
||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||
|
@ -52,6 +52,10 @@ macro_rules! check {
|
||||
//[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR mismatched types
|
||||
//[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR mismatched types
|
||||
//[free_inv_x_vs_free_inv_y]~^^^^^ ERROR mismatched types
|
||||
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
|
||||
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR mismatched types
|
||||
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR mismatched types
|
||||
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^^^ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,6 +91,9 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
// - if we are covariant, then 'a and 'b can be set to the call-site
|
||||
// intersection;
|
||||
// - if we are contravariant, then 'a can be inferred to 'static.
|
||||
//
|
||||
// FIXME(#32330) this is true, but we are not currently impl'ing this
|
||||
// full semantics
|
||||
check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
|
||||
for<'a> fn(&'a u32, &'a u32)) }
|
||||
check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
|
||||
@ -109,8 +116,4 @@ fn main() {
|
||||
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful
|
||||
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful
|
||||
//[free_x_vs_free_x]~^^^^^ ERROR compilation successful
|
||||
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR compilation successful
|
||||
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR compilation successful
|
||||
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR compilation successful
|
||||
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^^^ ERROR compilation successful
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ trait SomeTrait { fn get(&self) -> isize; }
|
||||
fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
|
||||
box v as Box<SomeTrait+'static>
|
||||
//~^ ERROR the parameter type `A` may not live long enough
|
||||
//~^^ ERROR the parameter type `A` may not live long enough
|
||||
//~| ERROR the parameter type `A` may not live long enough
|
||||
}
|
||||
|
||||
fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
|
||||
@ -28,7 +28,8 @@ fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
|
||||
|
||||
fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
|
||||
box v as Box<SomeTrait+'b>
|
||||
//~^ ERROR E0478
|
||||
//~^ ERROR the parameter type `A` may not live long enough
|
||||
//~| ERROR the parameter type `A` may not live long enough
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
Loading…
Reference in New Issue
Block a user