diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 3e227872848ef..42e4338ca3073 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -368,7 +368,6 @@ for ty::RegionParameterDef { name, def_id, index, - issue_32330: _, pure_wrt_drop } = *self; diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 77ec866dc8087..8e8576b83e4ed 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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 \ - ")); - } - _ => {} - } - } - 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) } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 541a9978341f6..9ecc8b0e66b9b 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -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 { 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, } 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(&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) + }) } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7154ce9e38f5e..bf79becfe4a10 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -299,7 +299,7 @@ pub enum RegionVariableOrigin { Coercion(Span), // Region variables created as the values for early-bound regions - EarlyBoundRegion(Span, ast::Name, Option), + 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>> { 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 }) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c4f785757cee1..13efa94a5c948 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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, - // For each type and trait definition, maps type parameters // to the trait object lifetime defaults computed from them. pub object_lifetime_defaults: NodeMap>, @@ -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(&mut self, - fn_id: ast::NodeId, parent_id: Option, 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; } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b5284852747f9..cae1eba5797cf 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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>, - 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); } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 3442cf0ef698a..86a4f66918965 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -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>), - RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>, Option>), + RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), + RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), Sorts(ExpectedFound>), IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), @@ -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, ""); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 804f47b5283f2..2ee7149fc1311 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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, /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute /// on generic parameter `'a`, asserts data of lifetime `'a` diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f261a56cdccdd..48ace804995ab 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -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), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5f89714b33fda..b42180b288bf6 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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)] diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bb6e478738aa2..1ec850ad7f349 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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 = 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, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7f69885047b93..cb22dcc21de22 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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> { 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)) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8780131bbcc26..f25a6cf58a79e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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::>(); diff --git a/src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs index c5557cee7cc1d..0e822aff01e87 100644 --- a/src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs +++ b/src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs @@ -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 diff --git a/src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs b/src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs index a15422e42d94a..10fe612980d34 100644 --- a/src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs @@ -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 diff --git a/src/test/compile-fail/hr-subtype.rs b/src/test/compile-fail/hr-subtype.rs index 95e469ebcfd72..c88d74d53ce94 100644 --- a/src/test/compile-fail/hr-subtype.rs +++ b/src/test/compile-fail/hr-subtype.rs @@ -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>), diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 0c7b44af949b6..1598a8a40d2f0 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -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 error: aborting due to previous error