X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc%2Finfer%2Fopaque_types%2Fmod.rs;h=9b197c1ecb14076ff8c38d2a5bf5d20e19ced3ba;hb=7ae0618e0af852c3e777272a29419f85eaf033cc;hp=9ed60b1f0c1120bc3fa03f08caa21ad20fd198d9;hpb=82cf3a4486bc882207a09bf0d9e2dea4632781aa;p=rust.git diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 9ed60b1f0c1..a1afb1a86be 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -1,19 +1,19 @@ -use crate::hir; -use crate::hir::def_id::DefId; -use crate::hir::Node; -use crate::infer::outlives::free_region_map::FreeRegionRelations; +use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region}; use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; use crate::middle::region; use crate::traits::{self, PredicateObligation}; use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use crate::ty::subst::{InternalSubsts, GenericArg, SubstsRef, GenericArgKind}; +use crate::ty::free_region_map::FreeRegionRelations; +use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt}; -use crate::util::nodemap::DefIdMap; -use errors::DiagnosticBuilder; use rustc::session::config::nightly_options; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use syntax_pos::Span; +use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, DefIdMap}; +use rustc_hir::Node; +use rustc_span::Span; use rustc_error_codes::*; @@ -24,6 +24,9 @@ /// appear in the return type). #[derive(Copy, Clone, Debug)] pub struct OpaqueTypeDecl<'tcx> { + /// The opaque type (`ty::Opaque`) for this declaration. + pub opaque_type: Ty<'tcx>, + /// The substitutions that we apply to the opaque type that this /// `impl Trait` desugars to. e.g., if: /// @@ -347,7 +350,8 @@ pub fn constrain_opaque_type>( debug!("constrain_opaque_type: bounds={:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); - let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates); + let required_region_bounds = + required_region_bounds(tcx, opaque_type, bounds.predicates); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -463,13 +467,15 @@ fn generate_member_constraint( concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { tcx: self.tcx, - op: |r| self.member_constraint( - opaque_type_def_id, - opaque_defn.definition_span, - concrete_ty, - r, - &choice_regions, - ), + op: |r| { + self.member_constraint( + opaque_type_def_id, + opaque_defn.definition_span, + concrete_ty, + r, + &choice_regions, + ) + }, }); } @@ -518,9 +524,7 @@ fn member_constraint_feature_gate( err.span_label(span, label); if nightly_options::is_nightly_build() { - help!(err, - "add #![feature(member_constraints)] to the crate attributes \ - to enable"); + err.help("add #![feature(member_constraints)] to the crate attributes to enable"); } err.emit(); @@ -618,7 +622,8 @@ pub fn unexpected_hidden_region_diagnostic( // // (*) if not, the `tainted_by_errors` flag would be set to // true in any case, so we wouldn't be here at all. - tcx.note_and_explain_free_region( + note_and_explain_free_region( + tcx, &mut err, &format!("hidden type `{}` captures ", hidden_ty), hidden_region, @@ -643,7 +648,8 @@ pub fn unexpected_hidden_region_diagnostic( // If the `region_scope_tree` is available, this is being // invoked from the "region inferencer error". We can at // least report a really cryptic error for now. - tcx.note_and_explain_region( + note_and_explain_region( + tcx, region_scope_tree, &mut err, &format!("hidden type `{}` captures ", hidden_ty), @@ -835,26 +841,28 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { self.opaque_type_def_id, hidden_ty, r, - ).emit(); + ) + .emit(); } } self.tcx.lifetimes.re_empty } None => { - self.tcx.sess - .struct_span_err( - self.span, - "non-defining opaque type use in defining scope" - ) + self.tcx + .sess + .struct_span_err(self.span, "non-defining opaque type use in defining scope") .span_label( self.span, - format!("lifetime `{}` is part of concrete type but not used in \ - parameter list of the `impl Trait` type alias", r), + format!( + "lifetime `{}` is part of concrete type but not used in \ + parameter list of the `impl Trait` type alias", + r + ), ) .emit(); self.tcx().mk_region(ty::ReStatic) - }, + } } } @@ -886,32 +894,30 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { // during codegen. let generics = self.tcx.generics_of(def_id); - let substs = - self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); self.tcx.mk_closure(def_id, substs) } ty::Generator(def_id, substs, movability) => { let generics = self.tcx.generics_of(def_id); - let substs = - self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); self.tcx.mk_generator(def_id, substs, movability) } @@ -924,12 +930,15 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { Some(GenericArgKind::Type(t1)) => t1, Some(u) => panic!("type mapped to unexpected kind: {:?}", u), None => { - self.tcx.sess + self.tcx + .sess .struct_span_err( self.span, - &format!("type parameter `{}` is part of concrete type but not \ + &format!( + "type parameter `{}` is part of concrete type but not \ used in parameter list for the `impl Trait` type alias", - ty), + ty + ), ) .emit(); @@ -954,12 +963,15 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { Some(GenericArgKind::Const(c1)) => c1, Some(u) => panic!("const mapped to unexpected kind: {:?}", u), None => { - self.tcx.sess + self.tcx + .sess .struct_span_err( self.span, - &format!("const parameter `{}` is part of concrete type but not \ + &format!( + "const parameter `{}` is part of concrete type but not \ used in parameter list for the `impl Trait` type alias", - ct) + ct + ), ) .emit(); @@ -1031,8 +1043,7 @@ fn instantiate_opaque_types_in_map>(&mut self, value: &T) let parent_def_id = self.parent_def_id; let def_scope_default = || { let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id == tcx.hir() - .local_def_id(opaque_parent_hir_id) + parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) }; let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) { Some(Node::Item(item)) => match item.kind { @@ -1048,29 +1059,17 @@ fn instantiate_opaque_types_in_map>(&mut self, value: &T) origin, .. }) => ( - may_define_opaque_type( - tcx, - self.parent_def_id, - opaque_hir_id, - ), + may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), origin, ), - _ => { - (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias) - } + _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias), }, Some(Node::ImplItem(item)) => match item.kind { hir::ImplItemKind::OpaqueTy(_) => ( - may_define_opaque_type( - tcx, - self.parent_def_id, - opaque_hir_id, - ), + may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), hir::OpaqueTyOrigin::TypeAlias, ), - _ => { - (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias) - } + _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias), }, _ => bug!( "expected (impl) item, found {}", @@ -1131,7 +1130,7 @@ fn fold_opaque_ty( debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone()); + let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1150,6 +1149,7 @@ fn fold_opaque_ty( self.opaque_types.insert( def_id, OpaqueTypeDecl { + opaque_type: ty, substs, definition_span, concrete_ty: ty_var, @@ -1206,11 +1206,7 @@ fn fold_opaque_ty( /// Here, `def_id` is the `DefId` of the defining use of the opaque type (e.g., `f1` or `f2`), /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. /// For the above example, this function returns `true` for `f1` and `false` for `f2`. -pub fn may_define_opaque_type( - tcx: TyCtxt<'_>, - def_id: DefId, - opaque_hir_id: hir::HirId, -) -> bool { +pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir::HirId) -> bool { let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); // Named opaque types can be defined by any siblings or children of siblings. @@ -1229,3 +1225,67 @@ pub fn may_define_opaque_type( ); res } + +/// Given a set of predicates that apply to an object type, returns +/// the region bounds that the (erased) `Self` type must +/// outlive. Precisely *because* the `Self` type is erased, the +/// parameter `erased_self_ty` must be supplied to indicate what type +/// has been used to represent `Self` in the predicates +/// themselves. This should really be a unique type; `FreshTy(0)` is a +/// popular choice. +/// +/// N.B., in some cases, particularly around higher-ranked bounds, +/// this function returns a kind of conservative approximation. +/// That is, all regions returned by this function are definitely +/// required, but there may be other region bounds that are not +/// returned, as well as requirements like `for<'a> T: 'a`. +/// +/// Requires that trait definitions have been processed so that we can +/// elaborate predicates and walk supertraits. +// +// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's +// what this code should accept. +crate fn required_region_bounds( + tcx: TyCtxt<'tcx>, + erased_self_ty: Ty<'tcx>, + predicates: Vec>, +) -> Vec> { + debug!( + "required_region_bounds(erased_self_ty={:?}, predicates={:?})", + erased_self_ty, predicates + ); + + assert!(!erased_self_ty.has_escaping_bound_vars()); + + traits::elaborate_predicates(tcx, predicates) + .filter_map(|predicate| { + match predicate { + ty::Predicate::Projection(..) + | ty::Predicate::Trait(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::WellFormed(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::RegionOutlives(..) + | ty::Predicate::ConstEvaluatable(..) => None, + ty::Predicate::TypeOutlives(predicate) => { + // Search for a bound of the form `erased_self_ty + // : 'a`, but be wary of something like `for<'a> + // erased_self_ty : 'a` (we interpret a + // higher-ranked bound like that as 'static, + // though at present the code in `fulfill.rs` + // considers such bounds to be unsatisfiable, so + // it's kind of a moot point since you could never + // construct such an object, but this seems + // correct even if that code changes). + let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder(); + if t == &erased_self_ty && !r.has_escaping_bound_vars() { + Some(*r) + } else { + None + } + } + } + }) + .collect() +}