about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark-Simulacrum <mark.simulacrum@gmail.com>2016-11-25 19:15:25 -0700
committerMark-Simulacrum <mark.simulacrum@gmail.com>2016-11-28 18:09:15 -0700
commit9b803ec4217d37fe73f1f738f8007d5d6512a425 (patch)
tree817a5b16da71803c99c07b91c0a6c02f6c21827b
parentbb35d50cad5f452e80ff88ee957962966c28a9f6 (diff)
Remove auto_traits from PartitionedBounds
-rw-r--r--src/librustc_privacy/lib.rs7
-rw-r--r--src/librustc_typeck/astconv.rs93
-rw-r--r--src/librustc_typeck/collect.rs28
-rw-r--r--src/test/compile-fail/issue-16966.rs2
4 files changed, 73 insertions, 57 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index ee18968ff35..5aac23f0f5f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -71,7 +71,8 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn item_ty_level(&self, item_def_id: DefId) -> Option<AccessLevel> {
         let ty_def_id = match self.tcx.item_type(item_def_id).sty {
             ty::TyAdt(adt, _) => adt.did,
-            ty::TyTrait(ref obj) => obj.principal.def_id(),
+            ty::TyDynamic(ref obj, ..) if obj.principal().is_some() =>
+                obj.principal().unwrap().def_id(),
             ty::TyProjection(ref proj) => proj.trait_ref.def_id,
             _ => return Some(AccessLevel::Public)
         };
@@ -359,7 +360,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         let ty_def_id = match ty.sty {
             ty::TyAdt(adt, _) => Some(adt.did),
-            ty::TyTrait(ref obj) => Some(obj.principal.def_id()),
+            ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
             ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
             ty::TyFnDef(def_id, ..) |
             ty::TyAnon(def_id, _) => Some(def_id),
@@ -934,7 +935,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         let ty_def_id = match ty.sty {
             ty::TyAdt(adt, _) => Some(adt.did),
-            ty::TyTrait(ref obj) => Some(obj.principal.def_id()),
+            ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
             ty::TyProjection(ref proj) => {
                 if self.required_visibility == ty::Visibility::PrivateExternal {
                     // Conservatively approximate the whole type alias as public without
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 986d817a10c..9f3887a8768 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -962,7 +962,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                                                    ty.id,
                                                    path.segments.last().unwrap(),
                                                    span,
-                                                   partition_bounds(tcx, span, bounds))
+                                                   partition_bounds(bounds))
                 } else {
                     struct_span_err!(tcx.sess, ty.span, E0172,
                                      "expected a reference to a trait")
@@ -1045,11 +1045,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                                                         trait_segment,
                                                         &mut projection_bounds);
 
-        let PartitionedBounds { auto_traits,
-                                trait_bounds,
+        let PartitionedBounds { trait_bounds,
                                 region_bounds } =
             partitioned_bounds;
 
+        let (auto_traits, trait_bounds) = split_auto_traits(tcx, trait_bounds);
+
         if !trait_bounds.is_empty() {
             let b = &trait_bounds[0];
             let span = b.trait_ref.path.span;
@@ -1443,7 +1444,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                                                path_id,
                                                path.segments.last().unwrap(),
                                                span,
-                                               partition_bounds(tcx, span, &[]))
+                                               partition_bounds(&[]))
             }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
                 assert_eq!(opt_self_ty, None);
@@ -1897,7 +1898,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         ast_bounds: &[hir::TyParamBound])
         -> Ty<'tcx>
     {
-        let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]);
+        let mut partitioned_bounds = partition_bounds(ast_bounds);
 
         let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
             partitioned_bounds.trait_bounds.remove(0)
@@ -1982,49 +1983,62 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 }
 
 pub struct PartitionedBounds<'a> {
-    pub auto_traits: Vec<DefId>,
     pub trait_bounds: Vec<&'a hir::PolyTraitRef>,
     pub region_bounds: Vec<&'a hir::Lifetime>,
 }
 
-/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
-/// general trait bounds, and region bounds.
-pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                            _span: Span,
-                                            ast_bounds: &'b [hir::TyParamBound])
-                                            -> PartitionedBounds<'b>
+/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the
+/// remaining general trait bounds.
+fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                         trait_bounds: Vec<&'b hir::PolyTraitRef>)
+    -> (Vec<DefId>, Vec<&'b hir::PolyTraitRef>)
+{
+    let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.into_iter().partition(|bound| {
+        match bound.trait_ref.path.def {
+            Def::Trait(trait_did) => {
+                // Checks whether `trait_did` refers to one of the builtin
+                // traits, like `Send`, and adds it to `auto_traits` if so.
+                if Some(trait_did) == tcx.lang_items.send_trait() ||
+                    Some(trait_did) == tcx.lang_items.sync_trait() {
+                    let segments = &bound.trait_ref.path.segments;
+                    let parameters = &segments[segments.len() - 1].parameters;
+                    if !parameters.types().is_empty() {
+                        check_type_argument_count(tcx, bound.trait_ref.path.span,
+                                                  parameters.types().len(), &[]);
+                    }
+                    if !parameters.lifetimes().is_empty() {
+                        report_lifetime_number_error(tcx, bound.trait_ref.path.span,
+                                                     parameters.lifetimes().len(), 0);
+                    }
+                    true
+                } else {
+                    false
+                }
+            }
+            _ => false
+        }
+    });
+
+    let auto_traits = auto_traits.into_iter().map(|tr| {
+        if let Def::Trait(trait_did) = tr.trait_ref.path.def {
+            trait_did
+        } else {
+            unreachable!()
+        }
+    }).collect::<Vec<_>>();
+
+    (auto_traits, trait_bounds)
+}
+
+/// Divides a list of bounds from the AST into two groups: general trait bounds and region bounds
+pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(ast_bounds: &'b [hir::TyParamBound])
+    -> PartitionedBounds<'b>
 {
-    let mut auto_traits = Vec::new();
     let mut region_bounds = Vec::new();
     let mut trait_bounds = Vec::new();
     for ast_bound in ast_bounds {
         match *ast_bound {
             hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
-                match b.trait_ref.path.def {
-                    Def::Trait(trait_did) => {
-                        // Checks whether `trait_did` refers to one of the builtin
-                        // traits, like `Send`, and adds it to `auto_traits` if so.
-                        if Some(trait_did) == tcx.lang_items.send_trait() ||
-                            Some(trait_did) == tcx.lang_items.sync_trait() {
-                            auto_traits.push(trait_did);
-                            let segments = &b.trait_ref.path.segments;
-                            let parameters = &segments[segments.len() - 1].parameters;
-                            if !parameters.types().is_empty() {
-                                check_type_argument_count(tcx, b.trait_ref.path.span,
-                                                          parameters.types().len(), &[]);
-                            }
-                            if !parameters.lifetimes().is_empty() {
-                                report_lifetime_number_error(tcx, b.trait_ref.path.span,
-                                                             parameters.lifetimes().len(), 0);
-                            }
-                            continue; // success
-                        }
-                    }
-                    _ => {
-                        // Not a trait? that's an error, but it'll get
-                        // reported later.
-                    }
-                }
                 trait_bounds.push(b);
             }
             hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
@@ -2035,7 +2049,6 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     }
 
     PartitionedBounds {
-        auto_traits: auto_traits,
         trait_bounds: trait_bounds,
         region_bounds: region_bounds,
     }
@@ -2110,7 +2123,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected
 #[derive(PartialEq, Eq, Clone, Debug)]
 pub struct Bounds<'tcx> {
     pub region_bounds: Vec<&'tcx ty::Region>,
-    pub auto_traits: Vec<DefId>,
+    pub implicitly_sized: bool,
     pub trait_bounds: Vec<ty::PolyTraitRef<'tcx>>,
     pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2b69ac12a2c..8495c1b3fb8 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1584,11 +1584,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     assert!(prev_predicates.is_none());
 }
 
-// Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
-                                       bounds: &mut Vec<DefId>,
-                                       ast_bounds: &[hir::TyParamBound],
-                                       span: Span)
+// Is it marked with ?Sized
+fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                ast_bounds: &[hir::TyParamBound],
+                                span: Span) -> bool
 {
     let tcx = astconv.tcx();
 
@@ -1621,11 +1620,13 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
             }
         }
         _ if kind_id.is_ok() => {
-            bounds.push(kind_id.unwrap());
+            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
@@ -1907,14 +1908,9 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 {
     let tcx = astconv.tcx();
     let PartitionedBounds {
-        mut auto_traits,
         trait_bounds,
         region_bounds
-    } = partition_bounds(tcx, span, &ast_bounds);
-
-    if let SizedByDefault::Yes = sized_by_default {
-        add_unsized_bound(astconv, &mut auto_traits, ast_bounds, span);
-    }
+    } = partition_bounds(&ast_bounds);
 
     let mut projection_bounds = vec![];
 
@@ -1932,9 +1928,15 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 
     trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
 
+    let implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
+        !is_unsized(astconv, ast_bounds, span)
+    } else {
+        false
+    };
+
     Bounds {
         region_bounds: region_bounds,
-        auto_traits: auto_traits,
+        implicitly_sized: implicitly_sized,
         trait_bounds: trait_bounds,
         projection_bounds: projection_bounds,
     }
diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs
index 5dbf7546de2..508442fcb94 100644
--- a/src/test/compile-fail/issue-16966.rs
+++ b/src/test/compile-fail/issue-16966.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:type annotations required
+// error-pattern:type annotations or generic parameter binding required
 fn main() {
     panic!(
         std::default::Default::default()