]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/infer/opaque_types/mod.rs
Rollup merge of #68050 - Centril:canon-error, r=Mark-Simulacrum
[rust.git] / src / librustc / infer / opaque_types / mod.rs
index 9b197c1ecb14076ff8c38d2a5bf5d20e19ced3ba..a1afb1a86be44b563fe1382167d8ca1284267bf4 100644 (file)
@@ -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,7 +24,6 @@
 /// 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>,
 
@@ -351,7 +350,8 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
             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 {
@@ -467,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,
+                )
+            },
         });
     }
 
@@ -522,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();
@@ -622,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,
@@ -647,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),
@@ -839,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)
-            },
+            }
         }
     }
 
@@ -890,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)
             }
@@ -928,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();
 
@@ -958,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();
 
@@ -1035,8 +1043,7 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&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 {
@@ -1052,29 +1059,17 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&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 {}",
@@ -1135,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
@@ -1211,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.
@@ -1234,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<ty::Predicate<'tcx>>,
+) -> Vec<ty::Region<'tcx>> {
+    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()
+}