]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/collect.rs
Turn `#[allocator]` into a built-in attribute and rename it to `#[rustc_allocator]`
[rust.git] / src / librustc_typeck / collect.rs
index 3034cacf6253f966a98d1971db00de78995358ba..f738f90b31eb6320a47357939ef8bcbfe82edf19 100644 (file)
@@ -1,6 +1,6 @@
 //! "Collection" is the process of determining the type and other external
 //! details of each item in Rust. Collection is specifically concerned
-//! with *interprocedural* things -- for example, for a function
+//! with *inter-procedural* things -- for example, for a function
 //! definition, collection will figure out the type and signature of the
 //! function, but it will not visit the *body* of the function in any way,
 //! nor examine type annotations on local variables (that's the job of
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
-use crate::astconv::{AstConv, Bounds};
+use crate::astconv::{AstConv, Bounds, SizedByDefault};
 use crate::constrained_generic_params as cgp;
 use crate::check::intrinsic::intrisic_operation_unsafety;
 use crate::lint;
-use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
 use rustc::mir::mono::Linkage;
@@ -233,7 +232,7 @@ fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn set_tainted_by_errors(&self) {
-        // no obvious place to track this, just let it go
+        // no obvious place to track this, so just let it go
     }
 
     fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
@@ -447,7 +446,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: hir::HirId) {
             }
         }
 
-        // Desugared from `impl Trait` -> visited by the function's return type
+        // Desugared from `impl Trait`, so visited by the function's return type.
         hir::ItemKind::Existential(hir::ExistTy {
             impl_trait_fn: Some(_),
             ..
@@ -704,7 +703,8 @@ fn super_predicates_of<'a, 'tcx>(
 
     // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
     let self_param_ty = tcx.mk_self_type();
-    let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
+    let superbounds1 = AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No,
+        item.span);
 
     let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
 
@@ -1218,7 +1218,7 @@ pub fn checked_type_of<'a, 'tcx>(
                     impl_trait_fn: None,
                     ..
                 }) => find_existential_constraints(tcx, def_id),
-                // existential types desugared from impl Trait
+                // Existential types desugared from `impl Trait`.
                 ItemKind::Existential(hir::ExistTy {
                     impl_trait_fn: Some(owner),
                     ..
@@ -1472,11 +1472,13 @@ fn find_existential_constraints<'a, 'tcx>(
 ) -> Ty<'tcx> {
     use rustc::hir::{ImplItem, Item, TraitItem};
 
+    debug!("find_existential_constraints({:?})", def_id);
+
     struct ConstraintLocator<'a, 'tcx: 'a> {
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         def_id: DefId,
-        // First found type span, actual type, mapping from the existential type's generic
-        // parameters to the concrete type's generic parameters
+        // (first found type span, actual type, mapping from the existential type's generic
+        // parameters to the concrete type's generic parameters)
         //
         // The mapping is an index for each use site of a generic parameter in the concrete type
         //
@@ -1486,10 +1488,13 @@ struct ConstraintLocator<'a, 'tcx: 'a> {
 
     impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> {
         fn check(&mut self, def_id: DefId) {
-            trace!("checking {:?}", def_id);
-            // don't try to check items that cannot possibly constrain the type
+            // Don't try to check items that cannot possibly constrain the type.
             if !self.tcx.has_typeck_tables(def_id) {
-                trace!("no typeck tables for {:?}", def_id);
+                debug!(
+                    "find_existential_constraints: no constraint for `{:?}` at `{:?}`: no tables",
+                    self.def_id,
+                    def_id,
+                );
                 return;
             }
             let ty = self
@@ -1498,22 +1503,32 @@ fn check(&mut self, def_id: DefId) {
                 .concrete_existential_types
                 .get(&self.def_id);
             if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
-                // FIXME(oli-obk): trace the actual span from inference to improve errors
+                debug!(
+                    "find_existential_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
+                    self.def_id,
+                    def_id,
+                    ty,
+                );
+
+                // FIXME(oli-obk): trace the actual span from inference to improve errors.
                 let span = self.tcx.def_span(def_id);
                 // used to quickly look up the position of a generic parameter
                 let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
-                // skip binder is ok, since we only use this to find generic parameters and their
-                // positions.
+                // Skipping binder is ok, since we only use this to find generic parameters and
+                // their positions.
                 for (idx, subst) in substs.iter().enumerate() {
                     if let UnpackedKind::Type(ty) = subst.unpack() {
                         if let ty::Param(p) = ty.sty {
                             if index_map.insert(p, idx).is_some() {
-                                // there was already an entry for `p`, meaning a generic parameter
-                                // was used twice
+                                // There was already an entry for `p`, meaning a generic parameter
+                                // was used twice.
                                 self.tcx.sess.span_err(
                                     span,
-                                    &format!("defining existential type use restricts existential \
-                                    type by using the generic parameter `{}` twice", p.name),
+                                    &format!(
+                                        "defining existential type use restricts existential \
+                                         type by using the generic parameter `{}` twice",
+                                        p.name
+                                    ),
                                 );
                                 return;
                             }
@@ -1528,8 +1543,8 @@ fn check(&mut self, def_id: DefId) {
                         }
                     }
                 }
-                // compute the index within the existential type for each generic parameter used in
-                // the concrete type
+                // Compute the index within the existential type for each generic parameter used in
+                // the concrete type.
                 let indices = concrete_type
                     .subst(self.tcx, substs)
                     .walk()
@@ -1550,14 +1565,15 @@ fn check(&mut self, def_id: DefId) {
                     let mut ty = concrete_type.walk().fuse();
                     let mut p_ty = prev_ty.walk().fuse();
                     let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) {
-                        // type parameters are equal to any other type parameter for the purpose of
+                        // Type parameters are equal to any other type parameter for the purpose of
                         // concrete type equality, as it is possible to obtain the same type just
                         // by passing matching parameters to a function.
                         (ty::Param(_), ty::Param(_)) => true,
                         _ => t == p,
                     });
                     if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
-                        // found different concrete types for the existential type
+                        debug!("find_existential_constraints: span={:?}", span);
+                        // Found different concrete types for the existential type.
                         let mut err = self.tcx.sess.struct_span_err(
                             span,
                             "concrete type differs from previous defining existential type use",
@@ -1569,7 +1585,7 @@ fn check(&mut self, def_id: DefId) {
                         err.span_note(prev_span, "previous use here");
                         err.emit();
                     } else if indices != *prev_indices {
-                        // found "same" concrete types, but the generic parameter order differs
+                        // Found "same" concrete types, but the generic parameter order differs.
                         let mut err = self.tcx.sess.struct_span_err(
                             span,
                             "concrete type's generic parameters differ from previous defining use",
@@ -1597,6 +1613,12 @@ fn check(&mut self, def_id: DefId) {
                 } else {
                     self.found = Some((span, concrete_type, indices));
                 }
+            } else {
+                debug!(
+                    "find_existential_constraints: no constraint for `{:?}` at `{:?}`",
+                    self.def_id,
+                    def_id,
+                );
             }
         }
     }
@@ -1607,7 +1629,7 @@ fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'thi
         }
         fn visit_item(&mut self, it: &'tcx Item) {
             let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
-            // the existential type itself or its children are not within its reveal scope
+            // The existential type itself or its children are not within its reveal scope.
             if def_id != self.def_id {
                 self.check(def_id);
                 intravisit::walk_item(self, it);
@@ -1615,7 +1637,7 @@ fn visit_item(&mut self, it: &'tcx Item) {
         }
         fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
             let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
-            // the existential type itself or its children are not within its reveal scope
+            // The existential type itself or its children are not within its reveal scope.
             if def_id != self.def_id {
                 self.check(def_id);
                 intravisit::walk_impl_item(self, it);
@@ -1628,26 +1650,28 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
         }
     }
 
+    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let scope = tcx.hir()
+        .get_defining_scope(hir_id)
+        .expect("could not get defining scope");
     let mut locator = ConstraintLocator {
         def_id,
         tcx,
         found: None,
     };
-    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let parent = tcx.hir().get_parent_item(hir_id);
 
-    trace!("parent_id: {:?}", parent);
+    debug!("find_existential_constraints: scope={:?}", scope);
 
-    if parent == hir::CRATE_HIR_ID {
+    if scope == hir::CRATE_HIR_ID {
         intravisit::walk_crate(&mut locator, tcx.hir().krate());
     } else {
-        trace!("parent: {:?}", tcx.hir().get_by_hir_id(parent));
-        match tcx.hir().get_by_hir_id(parent) {
+        debug!("find_existential_constraints: scope={:?}", tcx.hir().get_by_hir_id(scope));
+        match tcx.hir().get_by_hir_id(scope) {
             Node::Item(ref it) => intravisit::walk_item(&mut locator, it),
             Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it),
             Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it),
             other => bug!(
-                "{:?} is not a valid parent of an existential type item",
+                "{:?} is not a valid scope for an existential type item",
                 other
             ),
         }
@@ -1765,57 +1789,6 @@ fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> hir::I
     }
 }
 
-// Is it marked with ?Sized
-fn is_unsized<'gcx: 'tcx, 'tcx>(
-    astconv: &dyn AstConv<'gcx, 'tcx>,
-    ast_bounds: &[hir::GenericBound],
-    span: Span,
-) -> bool {
-    let tcx = astconv.tcx();
-
-    // Try to find an unbound in bounds.
-    let mut unbound = None;
-    for ab in ast_bounds {
-        if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
-            if unbound.is_none() {
-                unbound = Some(ptr.trait_ref.clone());
-            } else {
-                span_err!(
-                    tcx.sess,
-                    span,
-                    E0203,
-                    "type parameter has more than one relaxed default \
-                     bound, only one is supported"
-                );
-            }
-        }
-    }
-
-    let kind_id = tcx.lang_items().require(SizedTraitLangItem);
-    match unbound {
-        Some(ref tpb) => {
-            // FIXME(#8559) currently requires the unbound to be built-in.
-            if let Ok(kind_id) = kind_id {
-                if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
-                    tcx.sess.span_warn(
-                        span,
-                        "default bound relaxed for a type parameter, but \
-                         this does nothing because the given bound is not \
-                         a default. Only `?Sized` is supported",
-                    );
-                }
-            }
-        }
-        _ if kind_id.is_ok() => {
-            return false;
-        }
-        // No lang item for Sized, so we can't add it as a bound.
-        None => {}
-    }
-
-    true
-}
-
 /// Returns the early-bound lifetimes declared in this generics
 /// listing. For anything other than fns/methods, this is just all
 /// the lifetimes that are declared. For fns or methods, we have to
@@ -1960,8 +1933,8 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 let opaque_ty = tcx.mk_opaque(def_id, substs);
 
-                // Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`.
-                let bounds = compute_bounds(
+                // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
+                let bounds = AstConv::compute_bounds(
                     &icx,
                     opaque_ty,
                     bounds,
@@ -2006,8 +1979,8 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     let opaque_ty = tcx.mk_opaque(def_id, substs);
 
-                    // Collect the bounds, i.e., the `A+B+'c` in `impl A+B+'c`.
-                    let bounds = compute_bounds(
+                    // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
+                    let bounds = AstConv::compute_bounds(
                         &icx,
                         opaque_ty,
                         bounds,
@@ -2015,15 +1988,16 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                         tcx.def_span(def_id),
                     );
 
+                    let bounds_predicates = bounds.predicates(tcx, opaque_ty);
                     if impl_trait_fn.is_some() {
-                        // impl Trait
+                        // opaque types
                         return tcx.arena.alloc(ty::GenericPredicates {
                             parent: None,
-                            predicates: bounds.predicates(tcx, opaque_ty),
+                            predicates: bounds_predicates,
                         });
                     } else {
                         // named existential types
-                        predicates.extend(bounds.predicates(tcx, opaque_ty));
+                        predicates.extend(bounds_predicates);
                         generics
                     }
                 }
@@ -2093,7 +2067,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
     }
 
     // Collect the predicates that were written inline by the user on each
-    // type parameter (e.g., `<T:Foo>`).
+    // type parameter (e.g., `<T: Foo>`).
     for param in &ast_generics.params {
         if let GenericParamKind::Type { .. } = param.kind {
             let name = param.name.ident().as_interned_str();
@@ -2101,12 +2075,12 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
             index += 1;
 
             let sized = SizedByDefault::Yes;
-            let bounds = compute_bounds(&icx, param_ty, &param.bounds, sized, param.span);
+            let bounds = AstConv::compute_bounds(&icx, param_ty, &param.bounds, sized, param.span);
             predicates.extend(bounds.predicates(tcx, param_ty));
         }
     }
 
-    // Add in the bounds that appear in the where-clause
+    // Add in the bounds that appear in the where-clause.
     let where_clause = &ast_generics.where_clause;
     for predicate in &where_clause.predicates {
         match predicate {
@@ -2136,19 +2110,17 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                 for bound in bound_pred.bounds.iter() {
                     match bound {
                         &hir::GenericBound::Trait(ref poly_trait_ref, _) => {
-                            let mut projections = Vec::new();
+                            let mut bounds = Bounds::default();
 
                             let (trait_ref, _) = AstConv::instantiate_poly_trait_ref(
                                 &icx,
                                 poly_trait_ref,
                                 ty,
-                                &mut projections,
+                                &mut bounds,
                             );
 
-                            predicates.extend(
-                                iter::once((trait_ref.to_predicate(), poly_trait_ref.span)).chain(
-                                    projections.iter().map(|&(p, span)| (p.to_predicate(), span)
-                            )));
+                            predicates.push((trait_ref.to_predicate(), poly_trait_ref.span));
+                            predicates.extend(bounds.predicates(tcx, ty));
                         }
 
                         &hir::GenericBound::Outlives(ref lifetime) => {
@@ -2187,14 +2159,14 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
             let trait_item = tcx.hir().trait_item(trait_item_ref.id);
             let bounds = match trait_item.node {
                 hir::TraitItemKind::Type(ref bounds, _) => bounds,
-                _ => return vec![].into_iter()
+                _ => return Vec::new().into_iter()
             };
 
             let assoc_ty =
                 tcx.mk_projection(tcx.hir().local_def_id_from_hir_id(trait_item.hir_id),
                     self_trait_ref.substs);
 
-            let bounds = compute_bounds(
+            let bounds = AstConv::compute_bounds(
                 &ItemCtxt::new(tcx, def_id),
                 assoc_ty,
                 bounds,
@@ -2236,68 +2208,6 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
     result
 }
 
-pub enum SizedByDefault {
-    Yes,
-    No,
-}
-
-/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
-/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
-/// built-in trait `Send`.
-pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
-    astconv: &dyn AstConv<'gcx, 'tcx>,
-    param_ty: Ty<'tcx>,
-    ast_bounds: &[hir::GenericBound],
-    sized_by_default: SizedByDefault,
-    span: Span,
-) -> Bounds<'tcx> {
-    let mut region_bounds = Vec::new();
-    let mut trait_bounds = Vec::new();
-
-    for ast_bound in ast_bounds {
-        match *ast_bound {
-            hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b),
-            hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
-            hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
-        }
-    }
-
-    let mut projection_bounds = Vec::new();
-
-    let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
-        let (poly_trait_ref, _) = astconv.instantiate_poly_trait_ref(
-            bound,
-            param_ty,
-            &mut projection_bounds,
-        );
-        (poly_trait_ref, bound.span)
-    }).collect();
-
-    let region_bounds = region_bounds
-        .into_iter()
-        .map(|r| (astconv.ast_region_to_region(r, None), r.span))
-        .collect();
-
-    trait_bounds.sort_by_key(|(t, _)| t.def_id());
-
-    let implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
-        if !is_unsized(astconv, ast_bounds, span) {
-            Some(span)
-        } else {
-            None
-        }
-    } else {
-        None
-    };
-
-    Bounds {
-        region_bounds,
-        implicitly_sized,
-        trait_bounds,
-        projection_bounds,
-    }
-}
-
 /// Converts a specific `GenericBound` from the AST into a set of
 /// predicates that apply to the self type. A vector is returned
 /// because this can be anywhere from zero predicates (`T: ?Sized` adds no
@@ -2310,13 +2220,11 @@ fn predicates_from_bound<'tcx>(
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     match *bound {
         hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
-            let mut projections = Vec::new();
-            let (pred, _) = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections);
-            iter::once((pred.to_predicate(), tr.span)).chain(
-                projections
-                    .into_iter()
-                    .map(|(p, span)| (p.to_predicate(), span))
-            ).collect()
+            let mut bounds = Bounds::default();
+            let (pred, _) = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut bounds);
+            iter::once((pred.to_predicate(), tr.span))
+                .chain(bounds.predicates(astconv.tcx(), param_ty))
+                .collect()
         }
         hir::GenericBound::Outlives(ref lifetime) => {
             let region = astconv.ast_region_to_region(lifetime, None);
@@ -2340,8 +2248,8 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     };
     let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl);
 
-    // feature gate SIMD types in FFI, since I (huonw) am not sure the
-    // ABIs are handled at all correctly.
+    // Feature gate SIMD types in FFI, since I am not sure that the
+    // ABIs are handled at all correctly. -huonw
     if abi != abi::Abi::RustIntrinsic
         && abi != abi::Abi::PlatformIntrinsic
         && !tcx.features().simd_ffi
@@ -2416,13 +2324,13 @@ fn from_target_feature(
     };
     let rust_features = tcx.features();
     for item in list {
-        // Only `enable = ...` is accepted in the meta item list
+        // Only `enable = ...` is accepted in the meta-item list.
         if !item.check_name(sym::enable) {
             bad_item(item.span());
             continue;
         }
 
-        // Must be of the form `enable = "..."` ( a string)
+        // Must be of the form `enable = "..."` (a string).
         let value = match item.value_str() {
             Some(value) => value,
             None => {
@@ -2431,9 +2339,9 @@ fn from_target_feature(
             }
         };
 
-        // We allow comma separation to enable multiple features
+        // We allow comma separation to enable multiple features.
         target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            // Only allow whitelisted features per platform
+            // Only allow whitelisted features per platform.
             let feature_gate = match whitelist.get(feature) {
                 Some(g) => g,
                 None => {
@@ -2457,7 +2365,7 @@ fn from_target_feature(
                 }
             };
 
-            // Only allow features whose feature gates have been enabled
+            // Only allow features whose feature gates have been enabled.
             let allowed = match feature_gate.as_ref().map(|s| *s) {
                 Some(sym::arm_target_feature) => rust_features.arm_target_feature,
                 Some(sym::aarch64_target_feature) => rust_features.aarch64_target_feature,
@@ -2537,7 +2445,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
     for attr in attrs.iter() {
         if attr.check_name(sym::cold) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-        } else if attr.check_name(sym::allocator) {
+        } else if attr.check_name(sym::rustc_allocator) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
         } else if attr.check_name(sym::unwind) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::UNWIND;
@@ -2545,7 +2453,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
             if tcx.is_foreign_item(id) {
                 codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
             } else {
-                // `#[ffi_returns_twice]` is only allowed `extern fn`s
+                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
                 struct_span_err!(
                     tcx.sess,
                     attr.span,