mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 19:53:46 +00:00
Cleanup some remains of hr_lifetime_in_assoc_type
compatibility lint
This commit is contained in:
parent
ad36f8feba
commit
80cf3f99f4
@ -368,7 +368,6 @@ for ty::RegionParameterDef {
|
||||
name,
|
||||
def_id,
|
||||
index,
|
||||
issue_32330: _,
|
||||
pure_wrt_drop
|
||||
} = *self;
|
||||
|
||||
|
@ -66,8 +66,7 @@ use hir::map as hir_map;
|
||||
use hir::def_id::DefId;
|
||||
use middle::region;
|
||||
use traits::{ObligationCause, ObligationCauseCode};
|
||||
use ty::{self, TyCtxt, TypeFoldable};
|
||||
use ty::{Region, Issue32330};
|
||||
use ty::{self, Region, TyCtxt, TypeFoldable};
|
||||
use ty::error::TypeError;
|
||||
use syntax::ast::DUMMY_NODE_ID;
|
||||
use syntax_pos::{Pos, Span};
|
||||
@ -713,35 +712,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.tcx.note_and_explain_type_err(diag, terr, span);
|
||||
}
|
||||
|
||||
pub fn note_issue_32330(&self,
|
||||
diag: &mut DiagnosticBuilder<'tcx>,
|
||||
terr: &TypeError<'tcx>)
|
||||
{
|
||||
debug!("note_issue_32330: terr={:?}", terr);
|
||||
match *terr {
|
||||
TypeError::RegionsInsufficientlyPolymorphic(_, _, Some(box Issue32330 {
|
||||
fn_def_id, region_name
|
||||
})) |
|
||||
TypeError::RegionsOverlyPolymorphic(_, _, Some(box Issue32330 {
|
||||
fn_def_id, region_name
|
||||
})) => {
|
||||
diag.note(
|
||||
&format!("lifetime parameter `{0}` declared on fn `{1}` \
|
||||
appears only in the return type, \
|
||||
but here is required to be higher-ranked, \
|
||||
which means that `{0}` must appear in both \
|
||||
argument and return types",
|
||||
region_name,
|
||||
self.tcx.item_path_str(fn_def_id)));
|
||||
diag.note(
|
||||
&format!("this error is the result of a recent bug fix; \
|
||||
for more information, see issue #33685 \
|
||||
<https://github.com/rust-lang/rust/issues/33685>"));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_and_explain_type_error(&self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
terr: &TypeError<'tcx>)
|
||||
@ -761,7 +731,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
|
||||
self.note_issue_32330(&mut diag, terr);
|
||||
diag
|
||||
}
|
||||
|
||||
@ -934,7 +903,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
format!(" for lifetime parameter {}in trait containing associated type `{}`",
|
||||
br_string(br), type_name)
|
||||
}
|
||||
infer::EarlyBoundRegion(_, name, _) => {
|
||||
infer::EarlyBoundRegion(_, name) => {
|
||||
format!(" for lifetime parameter `{}`",
|
||||
name)
|
||||
}
|
||||
|
@ -13,9 +13,7 @@
|
||||
|
||||
use super::{CombinedSnapshot,
|
||||
InferCtxt,
|
||||
LateBoundRegion,
|
||||
HigherRankedType,
|
||||
RegionVariableOrigin,
|
||||
SubregionOrigin,
|
||||
SkolemizationMap};
|
||||
use super::combine::CombineFields;
|
||||
@ -29,15 +27,6 @@ use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
pub struct HrMatchResult<U> {
|
||||
pub value: U,
|
||||
|
||||
/// Normally, when we do a higher-ranked match operation, we
|
||||
/// expect all higher-ranked regions to be constrained as part of
|
||||
/// the match operation. However, in the transition period for
|
||||
/// #32330, it can happen that we sometimes have unconstrained
|
||||
/// regions that get instantiated with fresh variables. In that
|
||||
/// case, we collect the set of unconstrained bound regions here
|
||||
/// and replace them with fresh variables.
|
||||
pub unconstrained_regions: Vec<ty::BoundRegion>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||
@ -108,7 +97,6 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||
/// that do not appear in `T`. If that happens, those regions are
|
||||
/// unconstrained, and this routine replaces them with `'static`.
|
||||
pub fn higher_ranked_match<T, U>(&mut self,
|
||||
span: Span,
|
||||
a_pair: &Binder<(T, U)>,
|
||||
b_match: &T,
|
||||
a_is_expected: bool)
|
||||
@ -158,28 +146,16 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||
// be any region from the sets above, except for other members of
|
||||
// `skol_map`. There should always be a representative if things
|
||||
// are properly well-formed.
|
||||
let mut unconstrained_regions = vec![];
|
||||
let skol_representatives: FxHashMap<_, _> =
|
||||
skol_resolution_map
|
||||
.iter()
|
||||
.map(|(&skol, &(br, ref regions))| {
|
||||
.map(|(&skol, &(_, ref regions))| {
|
||||
let representative =
|
||||
regions.iter()
|
||||
.filter(|&&r| !skol_resolution_map.contains_key(r))
|
||||
.cloned()
|
||||
.next()
|
||||
.unwrap_or_else(|| { // [1]
|
||||
unconstrained_regions.push(br);
|
||||
self.infcx.next_region_var(
|
||||
LateBoundRegion(span, br, HigherRankedType))
|
||||
});
|
||||
|
||||
// [1] There should always be a representative,
|
||||
// unless the higher-ranked region did not appear
|
||||
// in the values being matched. We should reject
|
||||
// as ill-formed cases that can lead to this, but
|
||||
// right now we sometimes issue warnings (see
|
||||
// #32330).
|
||||
.expect("no representative region");
|
||||
|
||||
(skol, representative)
|
||||
})
|
||||
@ -216,10 +192,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||
// We are now done with these skolemized variables.
|
||||
self.infcx.pop_skolemized(skol_map, snapshot);
|
||||
|
||||
Ok(HrMatchResult {
|
||||
value: a_value,
|
||||
unconstrained_regions,
|
||||
})
|
||||
Ok(HrMatchResult { value: a_value })
|
||||
});
|
||||
}
|
||||
|
||||
@ -657,28 +630,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
skol_br,
|
||||
tainted_region);
|
||||
|
||||
let issue_32330 = if let &ty::ReVar(vid) = tainted_region {
|
||||
match self.region_vars.var_origin(vid) {
|
||||
RegionVariableOrigin::EarlyBoundRegion(_, _, issue_32330) => {
|
||||
issue_32330.map(Box::new)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if overly_polymorphic {
|
||||
return Err(if overly_polymorphic {
|
||||
debug!("Overly polymorphic!");
|
||||
return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
|
||||
tainted_region,
|
||||
issue_32330));
|
||||
TypeError::RegionsOverlyPolymorphic(skol_br, tainted_region)
|
||||
} else {
|
||||
debug!("Not as polymorphic!");
|
||||
return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
|
||||
tainted_region,
|
||||
issue_32330));
|
||||
}
|
||||
TypeError::RegionsInsufficientlyPolymorphic(skol_br, tainted_region)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ pub enum RegionVariableOrigin {
|
||||
Coercion(Span),
|
||||
|
||||
// Region variables created as the values for early-bound regions
|
||||
EarlyBoundRegion(Span, ast::Name, Option<ty::Issue32330>),
|
||||
EarlyBoundRegion(Span, ast::Name),
|
||||
|
||||
// Region variables created for bound regions
|
||||
// in a function or method that is called
|
||||
@ -989,7 +989,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
def: &ty::RegionParameterDef)
|
||||
-> ty::Region<'tcx> {
|
||||
self.next_region_var(EarlyBoundRegion(span, def.name, def.issue_32330))
|
||||
self.next_region_var(EarlyBoundRegion(span, def.name))
|
||||
}
|
||||
|
||||
/// Create a type inference variable for the given
|
||||
@ -1278,14 +1278,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
-> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
|
||||
{
|
||||
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty));
|
||||
let span = cause.span;
|
||||
let trace = TypeTrace {
|
||||
cause,
|
||||
values: TraitRefs(ExpectedFound::new(true, match_pair.skip_binder().0, match_b))
|
||||
};
|
||||
|
||||
let mut combine = self.combine_fields(trace, param_env);
|
||||
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
|
||||
let result = combine.higher_ranked_match(&match_pair, &match_b, true)?;
|
||||
Ok(InferOk { value: result, obligations: combine.obligations })
|
||||
}
|
||||
|
||||
|
@ -153,10 +153,6 @@ pub struct NamedRegionMap {
|
||||
// (b) it DOES appear in the arguments.
|
||||
pub late_bound: NodeSet,
|
||||
|
||||
// Contains the node-ids for lifetimes that were (incorrectly) categorized
|
||||
// as late-bound, until #32330 was fixed.
|
||||
pub issue_32330: NodeMap<ty::Issue32330>,
|
||||
|
||||
// For each type and trait definition, maps type parameters
|
||||
// to the trait object lifetime defaults computed from them.
|
||||
pub object_lifetime_defaults: NodeMap<Vec<ObjectLifetimeDefault>>,
|
||||
@ -261,7 +257,6 @@ pub fn krate(sess: &Session,
|
||||
let mut map = NamedRegionMap {
|
||||
defs: NodeMap(),
|
||||
late_bound: NodeSet(),
|
||||
issue_32330: NodeMap(),
|
||||
object_lifetime_defaults: compute_object_lifetime_defaults(sess, hir_map),
|
||||
};
|
||||
sess.track_errors(|| {
|
||||
@ -303,7 +298,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||
match item.node {
|
||||
hir::ItemFn(ref decl, _, _, _, ref generics, _) => {
|
||||
self.visit_early_late(item.id, None, decl, generics, |this| {
|
||||
self.visit_early_late(None, decl, generics, |this| {
|
||||
intravisit::walk_item(this, item);
|
||||
});
|
||||
}
|
||||
@ -355,7 +350,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
|
||||
match item.node {
|
||||
hir::ForeignItemFn(ref decl, _, ref generics) => {
|
||||
self.visit_early_late(item.id, None, decl, generics, |this| {
|
||||
self.visit_early_late(None, decl, generics, |this| {
|
||||
intravisit::walk_foreign_item(this, item);
|
||||
})
|
||||
}
|
||||
@ -406,7 +401,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
|
||||
if let hir::TraitItemKind::Method(ref sig, _) = trait_item.node {
|
||||
self.visit_early_late(
|
||||
trait_item.id,
|
||||
Some(self.hir_map.get_parent(trait_item.id)),
|
||||
&sig.decl, &sig.generics,
|
||||
|this| intravisit::walk_trait_item(this, trait_item))
|
||||
@ -418,7 +412,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
|
||||
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
self.visit_early_late(
|
||||
impl_item.id,
|
||||
Some(self.hir_map.get_parent(impl_item.id)),
|
||||
&sig.decl, &sig.generics,
|
||||
|this| intravisit::walk_impl_item(this, impl_item))
|
||||
@ -811,18 +804,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
/// bound lifetimes are resolved by name and associated with a binder id (`binder_id`), so the
|
||||
/// ordering is not important there.
|
||||
fn visit_early_late<F>(&mut self,
|
||||
fn_id: ast::NodeId,
|
||||
parent_id: Option<ast::NodeId>,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
generics: &'tcx hir::Generics,
|
||||
walk: F) where
|
||||
F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
|
||||
{
|
||||
let fn_def_id = self.hir_map.local_def_id(fn_id);
|
||||
insert_late_bound_lifetimes(self.map,
|
||||
fn_def_id,
|
||||
decl,
|
||||
generics);
|
||||
insert_late_bound_lifetimes(self.map, decl, generics);
|
||||
|
||||
// Find the start of nested early scopes, e.g. in methods.
|
||||
let mut index = 0;
|
||||
@ -1549,7 +1537,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
/// not amongst the inputs to a projection. In other words, `<&'a
|
||||
/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
|
||||
fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||
fn_def_id: DefId,
|
||||
decl: &hir::FnDecl,
|
||||
generics: &hir::Generics) {
|
||||
debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics);
|
||||
@ -1607,22 +1594,9 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||
// any `impl Trait` in the return type? early-bound.
|
||||
if appears_in_output.impl_trait { continue; }
|
||||
|
||||
// does not appear in the inputs, but appears in the return
|
||||
// type? eventually this will be early-bound, but for now we
|
||||
// just mark it so we can issue warnings.
|
||||
let constrained_by_input = constrained_by_input.regions.contains(&name);
|
||||
let appears_in_output = appears_in_output.regions.contains(&name);
|
||||
if !constrained_by_input && appears_in_output {
|
||||
debug!("inserting issue_32330 entry for {:?}, {:?} on {:?}",
|
||||
lifetime.lifetime.id,
|
||||
name,
|
||||
fn_def_id);
|
||||
map.issue_32330.insert(
|
||||
lifetime.lifetime.id,
|
||||
ty::Issue32330 {
|
||||
fn_def_id,
|
||||
region_name: name,
|
||||
});
|
||||
// does not appear in the inputs, but appears in the return type? early-bound.
|
||||
if !constrained_by_input.regions.contains(&name) &&
|
||||
appears_in_output.regions.contains(&name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -479,9 +479,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||
|
||||
let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
|
||||
match project_type(selcx, &obligation) {
|
||||
Ok(ProjectedTy::Progress(Progress { ty: projected_ty,
|
||||
mut obligations,
|
||||
cacheable })) => {
|
||||
Ok(ProjectedTy::Progress(Progress { ty: projected_ty, mut obligations })) => {
|
||||
// if projection succeeded, then what we get out of this
|
||||
// is also non-normalized (consider: it was derived from
|
||||
// an impl, where-clause etc) and hence we must
|
||||
@ -490,12 +488,10 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||
debug!("opt_normalize_projection_type: \
|
||||
projected_ty={:?} \
|
||||
depth={} \
|
||||
obligations={:?} \
|
||||
cacheable={:?}",
|
||||
obligations={:?}",
|
||||
projected_ty,
|
||||
depth,
|
||||
obligations,
|
||||
cacheable);
|
||||
obligations);
|
||||
|
||||
let result = if projected_ty.has_projection_types() {
|
||||
let mut normalizer = AssociatedTypeNormalizer::new(selcx,
|
||||
@ -520,8 +516,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||
obligations,
|
||||
}
|
||||
};
|
||||
infcx.projection_cache.borrow_mut()
|
||||
.complete(projection_ty, &result, cacheable);
|
||||
infcx.projection_cache.borrow_mut().complete(projection_ty, &result);
|
||||
Some(result)
|
||||
}
|
||||
Ok(ProjectedTy::NoProgress(projected_ty)) => {
|
||||
@ -532,8 +527,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||
value: projected_ty,
|
||||
obligations: vec![]
|
||||
};
|
||||
infcx.projection_cache.borrow_mut()
|
||||
.complete(projection_ty, &result, true);
|
||||
infcx.projection_cache.borrow_mut().complete(projection_ty, &result);
|
||||
Some(result)
|
||||
}
|
||||
Err(ProjectionTyError::TooManyCandidates) => {
|
||||
@ -606,7 +600,6 @@ enum ProjectedTy<'tcx> {
|
||||
struct Progress<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
obligations: Vec<PredicateObligation<'tcx>>,
|
||||
cacheable: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> Progress<'tcx> {
|
||||
@ -614,7 +607,6 @@ impl<'tcx> Progress<'tcx> {
|
||||
Progress {
|
||||
ty: tcx.types.err,
|
||||
obligations: vec![],
|
||||
cacheable: true
|
||||
}
|
||||
}
|
||||
|
||||
@ -1228,7 +1220,6 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
|
||||
Progress {
|
||||
ty: ty_match.value,
|
||||
obligations,
|
||||
cacheable: ty_match.unconstrained_regions.is_empty(),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@ -1272,7 +1263,6 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
|
||||
Progress {
|
||||
ty: ty.subst(tcx, substs),
|
||||
obligations: nested,
|
||||
cacheable: true
|
||||
}
|
||||
}
|
||||
|
||||
@ -1380,22 +1370,11 @@ impl<'tcx> ProjectionCache<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Indicates that `key` was normalized to `value`. If `cacheable` is false,
|
||||
/// then this result is sadly not cacheable.
|
||||
fn complete(&mut self,
|
||||
key: ty::ProjectionTy<'tcx>,
|
||||
value: &NormalizedTy<'tcx>,
|
||||
cacheable: bool) {
|
||||
let fresh_key = if cacheable {
|
||||
debug!("ProjectionCacheEntry::complete: adding cache entry: key={:?}, value={:?}",
|
||||
key, value);
|
||||
self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.value))
|
||||
} else {
|
||||
debug!("ProjectionCacheEntry::complete: cannot cache: key={:?}, value={:?}",
|
||||
key, value);
|
||||
!self.map.remove(key)
|
||||
};
|
||||
|
||||
/// Indicates that `key` was normalized to `value`.
|
||||
fn complete(&mut self, key: ty::ProjectionTy<'tcx>, value: &NormalizedTy<'tcx>) {
|
||||
debug!("ProjectionCacheEntry::complete: adding cache entry: key={:?}, value={:?}",
|
||||
key, value);
|
||||
let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.value));
|
||||
assert!(!fresh_key, "never started projecting `{:?}`", key);
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,8 @@ pub enum TypeError<'tcx> {
|
||||
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
|
||||
RegionsNotSame(Region<'tcx>, Region<'tcx>),
|
||||
RegionsNoOverlap(Region<'tcx>, Region<'tcx>),
|
||||
RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>, Option<Box<ty::Issue32330>>),
|
||||
RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>, Option<Box<ty::Issue32330>>),
|
||||
RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>),
|
||||
RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>),
|
||||
Sorts(ExpectedFound<Ty<'tcx>>),
|
||||
IntMismatch(ExpectedFound<ty::IntVarValue>),
|
||||
FloatMismatch(ExpectedFound<ast::FloatTy>),
|
||||
@ -116,13 +116,13 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
RegionsNoOverlap(..) => {
|
||||
write!(f, "lifetimes do not intersect")
|
||||
}
|
||||
RegionsInsufficientlyPolymorphic(br, _, _) => {
|
||||
RegionsInsufficientlyPolymorphic(br, _) => {
|
||||
write!(f,
|
||||
"expected bound lifetime parameter{}{}, found concrete lifetime",
|
||||
if br.is_named() { " " } else { "" },
|
||||
br)
|
||||
}
|
||||
RegionsOverlyPolymorphic(br, _, _) => {
|
||||
RegionsOverlyPolymorphic(br, _) => {
|
||||
write!(f,
|
||||
"expected concrete lifetime, found bound lifetime parameter{}{}",
|
||||
if br.is_named() { " " } else { "" },
|
||||
@ -257,15 +257,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.note_and_explain_region(db, "...does not overlap ",
|
||||
region2, "");
|
||||
}
|
||||
RegionsInsufficientlyPolymorphic(_, conc_region, _) => {
|
||||
RegionsInsufficientlyPolymorphic(_, conc_region) => {
|
||||
self.note_and_explain_region(db, "concrete lifetime that was found is ",
|
||||
conc_region, "");
|
||||
}
|
||||
RegionsOverlyPolymorphic(_, &ty::ReVar(_), _) => {
|
||||
RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => {
|
||||
// don't bother to print out the message below for
|
||||
// inference variables, it's not very illuminating.
|
||||
}
|
||||
RegionsOverlyPolymorphic(_, conc_region, _) => {
|
||||
RegionsOverlyPolymorphic(_, conc_region) => {
|
||||
self.note_and_explain_region(db, "expected concrete lifetime is ",
|
||||
conc_region, "");
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
|
||||
pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
|
||||
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
|
||||
pub use self::sty::RegionKind;
|
||||
pub use self::sty::Issue32330;
|
||||
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
|
||||
pub use self::sty::BoundRegion::*;
|
||||
pub use self::sty::InferTy::*;
|
||||
@ -676,7 +675,6 @@ pub struct RegionParameterDef {
|
||||
pub name: Name,
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
pub issue_32330: Option<ty::Issue32330>,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `'a`, asserts data of lifetime `'a`
|
||||
|
@ -346,13 +346,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
|
||||
RegionsNoOverlap(a, b) => {
|
||||
return tcx.lift(&(a, b)).map(|(a, b)| RegionsNoOverlap(a, b))
|
||||
}
|
||||
RegionsInsufficientlyPolymorphic(a, b, ref c) => {
|
||||
let c = c.clone();
|
||||
return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b, c))
|
||||
RegionsInsufficientlyPolymorphic(a, b) => {
|
||||
return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b))
|
||||
}
|
||||
RegionsOverlyPolymorphic(a, b, ref c) => {
|
||||
let c = c.clone();
|
||||
return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b, c))
|
||||
RegionsOverlyPolymorphic(a, b) => {
|
||||
return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b))
|
||||
}
|
||||
IntMismatch(x) => IntMismatch(x),
|
||||
FloatMismatch(x) => FloatMismatch(x),
|
||||
@ -1004,13 +1002,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
|
||||
RegionsNoOverlap(a, b) => {
|
||||
RegionsNoOverlap(a.fold_with(folder), b.fold_with(folder))
|
||||
},
|
||||
RegionsInsufficientlyPolymorphic(a, b, ref c) => {
|
||||
let c = c.clone();
|
||||
RegionsInsufficientlyPolymorphic(a, b.fold_with(folder), c)
|
||||
RegionsInsufficientlyPolymorphic(a, b) => {
|
||||
RegionsInsufficientlyPolymorphic(a, b.fold_with(folder))
|
||||
},
|
||||
RegionsOverlyPolymorphic(a, b, ref c) => {
|
||||
let c = c.clone();
|
||||
RegionsOverlyPolymorphic(a, b.fold_with(folder), c)
|
||||
RegionsOverlyPolymorphic(a, b) => {
|
||||
RegionsOverlyPolymorphic(a, b.fold_with(folder))
|
||||
},
|
||||
IntMismatch(x) => IntMismatch(x),
|
||||
FloatMismatch(x) => FloatMismatch(x),
|
||||
@ -1036,8 +1032,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
|
||||
RegionsNoOverlap(a, b) => {
|
||||
a.visit_with(visitor) || b.visit_with(visitor)
|
||||
},
|
||||
RegionsInsufficientlyPolymorphic(_, b, _) |
|
||||
RegionsOverlyPolymorphic(_, b, _) => {
|
||||
RegionsInsufficientlyPolymorphic(_, b) |
|
||||
RegionsOverlyPolymorphic(_, b) => {
|
||||
b.visit_with(visitor)
|
||||
},
|
||||
Sorts(x) => x.visit_with(visitor),
|
||||
|
@ -77,20 +77,6 @@ impl BoundRegion {
|
||||
}
|
||||
}
|
||||
|
||||
/// When a region changed from late-bound to early-bound when #32330
|
||||
/// was fixed, its `RegionParameterDef` will have one of these
|
||||
/// structures that we can use to give nicer errors.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub struct Issue32330 {
|
||||
/// fn where is region declared
|
||||
pub fn_def_id: DefId,
|
||||
|
||||
/// name of region; duplicates the info in BrNamed but convenient
|
||||
/// to have it here, and this code is only temporary
|
||||
pub region_name: ast::Name,
|
||||
}
|
||||
|
||||
/// NB: If you change this, you'll probably want to change the corresponding
|
||||
/// AST structure in libsyntax/ast.rs as well.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
|
@ -1110,46 +1110,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
hir::TyBareFn(ref bf) => {
|
||||
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
|
||||
let bare_fn_ty = self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl);
|
||||
|
||||
// Find any late-bound regions declared in return type that do
|
||||
// not appear in the arguments. These are not wellformed.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// for<'a> fn() -> &'a str <-- 'a is bad
|
||||
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok
|
||||
//
|
||||
// Note that we do this check **here** and not in
|
||||
// `ty_of_bare_fn` because the latter is also used to make
|
||||
// the types for fn items, and we do not want to issue a
|
||||
// warning then. (Once we fix #32330, the regions we are
|
||||
// checking for here would be considered early bound
|
||||
// anyway.)
|
||||
let inputs = bare_fn_ty.inputs();
|
||||
let late_bound_in_args = tcx.collect_constrained_late_bound_regions(
|
||||
&inputs.map_bound(|i| i.to_owned()));
|
||||
let output = bare_fn_ty.output();
|
||||
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
|
||||
for br in late_bound_in_ret.difference(&late_bound_in_args) {
|
||||
let br_name = match *br {
|
||||
ty::BrNamed(_, name) => name,
|
||||
_ => {
|
||||
span_bug!(
|
||||
bf.decl.output.span(),
|
||||
"anonymous bound region {:?} in return but not args",
|
||||
br);
|
||||
}
|
||||
};
|
||||
struct_span_err!(tcx.sess,
|
||||
ast_ty.span,
|
||||
E0581,
|
||||
"return type references lifetime `{}`, \
|
||||
which does not appear in the fn input types",
|
||||
br_name)
|
||||
.emit();
|
||||
}
|
||||
tcx.mk_fn_ptr(bare_fn_ty)
|
||||
tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl))
|
||||
}
|
||||
hir::TyTraitObject(ref bounds, ref lifetime) => {
|
||||
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
|
||||
@ -1269,23 +1230,56 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
-> ty::PolyFnSig<'tcx> {
|
||||
debug!("ty_of_fn");
|
||||
|
||||
let tcx = self.tcx();
|
||||
let input_tys: Vec<Ty> =
|
||||
decl.inputs.iter().map(|a| self.ty_of_arg(a, None)).collect();
|
||||
|
||||
let output_ty = match decl.output {
|
||||
hir::Return(ref output) => self.ast_ty_to_ty(output),
|
||||
hir::DefaultReturn(..) => self.tcx().mk_nil(),
|
||||
hir::DefaultReturn(..) => tcx.mk_nil(),
|
||||
};
|
||||
|
||||
debug!("ty_of_fn: output_ty={:?}", output_ty);
|
||||
|
||||
ty::Binder(self.tcx().mk_fn_sig(
|
||||
let bare_fn_ty = ty::Binder(tcx.mk_fn_sig(
|
||||
input_tys.into_iter(),
|
||||
output_ty,
|
||||
decl.variadic,
|
||||
unsafety,
|
||||
abi
|
||||
))
|
||||
));
|
||||
|
||||
// Find any late-bound regions declared in return type that do
|
||||
// not appear in the arguments. These are not wellformed.
|
||||
//
|
||||
// Example:
|
||||
// for<'a> fn() -> &'a str <-- 'a is bad
|
||||
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok
|
||||
let inputs = bare_fn_ty.inputs();
|
||||
let late_bound_in_args = tcx.collect_constrained_late_bound_regions(
|
||||
&inputs.map_bound(|i| i.to_owned()));
|
||||
let output = bare_fn_ty.output();
|
||||
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
|
||||
for br in late_bound_in_ret.difference(&late_bound_in_args) {
|
||||
let br_name = match *br {
|
||||
ty::BrNamed(_, name) => name,
|
||||
_ => {
|
||||
span_bug!(
|
||||
decl.output.span(),
|
||||
"anonymous bound region {:?} in return but not args",
|
||||
br);
|
||||
}
|
||||
};
|
||||
struct_span_err!(tcx.sess,
|
||||
decl.output.span(),
|
||||
E0581,
|
||||
"return type references lifetime `{}`, \
|
||||
which does not appear in the fn input types",
|
||||
br_name)
|
||||
.emit();
|
||||
}
|
||||
|
||||
bare_fn_ty
|
||||
}
|
||||
|
||||
pub fn ty_of_closure(&self,
|
||||
|
@ -1607,7 +1607,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
|
||||
-> Option<ty::Region<'tcx>> {
|
||||
let v = match def {
|
||||
Some(def) => infer::EarlyBoundRegion(span, def.name, def.issue_32330),
|
||||
Some(def) => infer::EarlyBoundRegion(span, def.name),
|
||||
None => infer::MiscVariable(span)
|
||||
};
|
||||
Some(self.next_region_var(v))
|
||||
|
@ -979,13 +979,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
|
||||
let regions = early_lifetimes.enumerate().map(|(i, l)| {
|
||||
let issue_32330 = tcx.named_region_map.issue_32330.get(&l.lifetime.id).cloned();
|
||||
ty::RegionParameterDef {
|
||||
name: l.lifetime.name,
|
||||
index: own_start + i as u32,
|
||||
def_id: tcx.hir.local_def_id(l.lifetime.id),
|
||||
pure_wrt_drop: l.pure_wrt_drop,
|
||||
issue_32330: issue_32330,
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
|
@ -43,23 +43,19 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
// FIXME(#32330)
|
||||
//#[cfg(transmute)] // one instantiations: BAD
|
||||
//fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||
// bar(foo, x) //[transmute] ERROR E0495
|
||||
//}
|
||||
#[cfg(transmute)] // one instantiations: BAD
|
||||
fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||
bar(foo, x) //[transmute]~ ERROR E0495
|
||||
}
|
||||
|
||||
// FIXME(#32330)
|
||||
//#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||
//fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
|
||||
// let a = bar(foo, y); //[krisskross] ERROR E0495
|
||||
// let b = bar(foo, x); //[krisskross] ERROR E0495
|
||||
// (a, b)
|
||||
//}
|
||||
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||
fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
|
||||
let a = bar(foo, y); //[krisskross]~ ERROR E0495
|
||||
let b = bar(foo, x); //[krisskross]~ ERROR E0495
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { }
|
||||
//[ok]~^ ERROR compilation successful
|
||||
//[oneuse]~^^ ERROR compilation successful
|
||||
//[transmute]~^^^ ERROR compilation successful
|
||||
//[krisskross]~^^^^ ERROR compilation successful
|
||||
|
@ -42,35 +42,29 @@ fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
// FIXME(#32330)
|
||||
//#[cfg(oneuse)] // one instantiation: BAD
|
||||
//fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
// let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
// let a = bar(f, x); //[oneuse] ERROR E0495
|
||||
// let b = bar(f, y);
|
||||
// (a, b)
|
||||
//}
|
||||
#[cfg(oneuse)] // one instantiation: BAD
|
||||
fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
let a = bar(f, x); //[oneuse]~^ ERROR E0495
|
||||
let b = bar(f, y);
|
||||
(a, b)
|
||||
}
|
||||
|
||||
// FIXME(#32330)
|
||||
//#[cfg(transmute)] // one instantiations: BAD
|
||||
//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
|
||||
//}
|
||||
#[cfg(transmute)] // one instantiations: BAD
|
||||
fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
|
||||
// Cannot instantiate `foo` with any lifetime other than `'a`,
|
||||
// since it is provided as input.
|
||||
|
||||
// FIXME(#32330)
|
||||
//#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||
//fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
// let a = bar(foo, y); //[krisskross] ERROR E0495
|
||||
// let b = bar(foo, x); //[krisskross] ERROR E0495
|
||||
// (a, b)
|
||||
//}
|
||||
bar(foo, x) //[transmute]~ ERROR E0495
|
||||
}
|
||||
|
||||
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||
fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let a = bar(foo, y); //[krisskross]~ ERROR E0495
|
||||
let b = bar(foo, x); //[krisskross]~ ERROR E0495
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { }
|
||||
//[ok]~^ ERROR compilation successful
|
||||
//[oneuse]~^^ ERROR compilation successful
|
||||
//[transmute]~^^^ ERROR compilation successful
|
||||
//[krisskross]~^^^^ ERROR compilation successful
|
||||
|
@ -91,9 +91,6 @@ 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>),
|
||||
|
@ -6,8 +6,6 @@ error[E0308]: mismatched types
|
||||
|
|
||||
= note: expected type `fn(&'cx S) -> &'cx S`
|
||||
found type `fn(&'a S) -> &S {bar::<'_>}`
|
||||
= note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types
|
||||
= note: this error is the result of a recent bug fix; for more information, see issue #33685 <https://github.com/rust-lang/rust/issues/33685>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user