diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-04-22 16:38:17 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-05-03 18:30:10 +0300 |
| commit | 05f1a057b6e59fd07b4af7a9a2f0101d67faba88 (patch) | |
| tree | 89b72843e31fc98ae1670741e197dfc29ed37cf0 | |
| parent | 6fc19ada6b2c6373b28e70a1dffda68dba96f9a1 (diff) | |
| download | rust-05f1a057b6e59fd07b4af7a9a2f0101d67faba88.tar.gz rust-05f1a057b6e59fd07b4af7a9a2f0101d67faba88.zip | |
address review comments
| -rw-r--r-- | src/librustc/ty/mod.rs | 156 | ||||
| -rw-r--r-- | src/test/run-pass/issue-31299.rs | 9 |
2 files changed, 83 insertions, 82 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b4156fde6a3..a61e8603dbb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1750,28 +1750,69 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> { } impl<'tcx> AdtDefData<'tcx, 'tcx> { - fn sized_constraint_for_tys<TYS>( - &'tcx self, - tcx: &ty::TyCtxt<'tcx>, - stack: &mut Vec<AdtDefMaster<'tcx>>, - tys: TYS - ) -> Ty<'tcx> - where TYS: IntoIterator<Item=Ty<'tcx>> + /// Calculates the Sized-constraint. + /// + /// As the Sized-constraint of enums can be a *set* of types, + /// the Sized-constraint may need to be a set also. Because introducing + /// a new type of IVar is currently a complex affair, the Sized-constraint + /// may be a tuple. + /// + /// In fact, there are only a few options for the constraint: + /// - `bool`, if the type is always Sized + /// - an obviously-unsized type + /// - a type parameter or projection whose Sizedness can't be known + /// - a tuple of type parameters or projections, if there are multiple + /// such. + /// - a TyError, if a type contained itself. The representability + /// check should catch this case. + fn calculate_sized_constraint_inner(&'tcx self, tcx: &ty::TyCtxt<'tcx>, + stack: &mut Vec<AdtDefMaster<'tcx>>) { - let tys : Vec<_> = tys.into_iter() - .map(|ty| self.sized_constraint_for_ty(tcx, stack, ty)) - .flat_map(|ty| match ty.sty { - ty::TyTuple(ref tys) => tys.last().cloned(), - _ => Some(ty) - }) - .filter(|ty| *ty != tcx.types.bool) - .collect(); - - match tys.len() { + + let dep_node = DepNode::SizedConstraint(self.did); + + if self.sized_constraint.get(dep_node).is_some() { + return; + } + + if stack.contains(&self) { + debug!("calculate_sized_constraint: {:?} is recursive", self); + // This should be reported as an error by `check_representable`. + // + // Consider the type as Sized in the meanwhile to avoid + // further errors. + self.sized_constraint.fulfill(dep_node, tcx.types.err); + return; + } + + stack.push(self); + + let tys : Vec<_> = + self.variants.iter().flat_map(|v| { + v.fields.last() + }).flat_map(|f| { + self.sized_constraint_for_ty(tcx, stack, f.unsubst_ty()) + }).collect(); + + let self_ = stack.pop().unwrap(); + assert_eq!(self_, self); + + let ty = match tys.len() { _ if tys.references_error() => tcx.types.err, 0 => tcx.types.bool, 1 => tys[0], _ => tcx.mk_tup(tys) + }; + + match self.sized_constraint.get(dep_node) { + Some(old_ty) => { + debug!("calculate_sized_constraint: {:?} recurred", self); + assert_eq!(old_ty, tcx.types.err) + } + None => { + debug!("calculate_sized_constraint: {:?} => {:?}", self, ty); + self.sized_constraint.fulfill(dep_node, ty) + } } } @@ -1780,22 +1821,23 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> { tcx: &ty::TyCtxt<'tcx>, stack: &mut Vec<AdtDefMaster<'tcx>>, ty: Ty<'tcx> - ) -> Ty<'tcx> { + ) -> Vec<Ty<'tcx>> { let result = match ty.sty { TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyArray(..) | TyClosure(..) => { - // these are always sized - return a primitive - tcx.types.bool + vec![] } TyStr | TyTrait(..) | TySlice(_) | TyError => { // these are never sized - return the target type - ty + vec![ty] } TyTuple(ref tys) => { - self.sized_constraint_for_tys(tcx, stack, tys.iter().cloned()) + tys.last().into_iter().flat_map(|ty| { + self.sized_constraint_for_ty(tcx, stack, ty) + }).collect() } TyEnum(adt, substs) | TyStruct(adt, substs) => { @@ -1808,13 +1850,19 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> { .subst(tcx, substs); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_ty); - self.sized_constraint_for_ty(tcx, stack, adt_ty) + if let ty::TyTuple(ref tys) = adt_ty.sty { + tys.iter().flat_map(|ty| { + self.sized_constraint_for_ty(tcx, stack, ty) + }).collect() + } else { + self.sized_constraint_for_ty(tcx, stack, adt_ty) + } } TyProjection(..) => { // must calculate explicitly. // FIXME: consider special-casing always-Sized projections - ty + vec![ty] } TyParam(..) => { @@ -1824,7 +1872,7 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> { let sized_trait = match tcx.lang_items.sized_trait() { Some(x) => x, - _ => return ty + _ => return vec![ty] }; let sized_predicate = Binder(TraitRef { def_id: sized_trait, @@ -1834,9 +1882,9 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> { }).to_predicate(); let predicates = tcx.lookup_predicates(self.did).predicates; if predicates.into_iter().any(|p| p == sized_predicate) { - tcx.types.bool + vec![] } else { - ty + vec![ty] } } @@ -1848,60 +1896,6 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> { debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result); result } - - /// Calculates the Sized-constraint. - /// - /// As the Sized-constraint of enums can be a *set* of types, - /// the Sized-constraint may need to be a set also. Because introducing - /// a new type of IVar is currently a complex affair, the Sized-constraint - /// may be a tuple. - /// - /// In fact, there are only a few options for the constraint: - /// - `bool`, if the type is always Sized - /// - an obviously-unsized type - /// - a type parameter or projection whose Sizedness can't be known - /// - a tuple of type parameters or projections, if there are multiple - /// such. - /// - a TyError, if a type contained itself. The representability - /// check should catch this case. - fn calculate_sized_constraint_inner(&'tcx self, tcx: &ty::TyCtxt<'tcx>, - stack: &mut Vec<AdtDefMaster<'tcx>>) - { - - let dep_node = DepNode::SizedConstraint(self.did); - - if self.sized_constraint.get(dep_node).is_some() { - return; - } - - if stack.contains(&self) { - debug!("calculate_sized_constraint: {:?} is recursive", self); - self.sized_constraint.fulfill(dep_node, tcx.types.err); - return; - } - - stack.push(self); - let ty = self.sized_constraint_for_tys( - tcx, stack, - self.variants.iter().flat_map(|v| { - v.fields.last() - }).map(|f| f.unsubst_ty()) - ); - - let self_ = stack.pop().unwrap(); - assert_eq!(self_, self); - - match self.sized_constraint.get(dep_node) { - Some(old_ty) => { - debug!("calculate_sized_constraint: {:?} recurred", self); - assert_eq!(old_ty, tcx.types.err) - } - None => { - debug!("calculate_sized_constraint: {:?} => {:?}", self, ty); - self.sized_constraint.fulfill(dep_node, ty) - } - } - } } impl<'tcx, 'container> VariantDefData<'tcx, 'container> { diff --git a/src/test/run-pass/issue-31299.rs b/src/test/run-pass/issue-31299.rs index e49e13c458f..6c04e66068e 100644 --- a/src/test/run-pass/issue-31299.rs +++ b/src/test/run-pass/issue-31299.rs @@ -12,12 +12,19 @@ // because of eager normalization: // // proving `M: Sized` requires -// - proving `PtrBack<Vec<M>>: Sized` requis +// - proving `PtrBack<Vec<M>>: Sized` requires // - normalizing `Vec<<Vec<M> as Front>::Back>>: Sized` requires // - proving `Vec<M>: Front` requires // - `M: Sized` <-- cycle! // // If we skip the normalization step, though, everything goes fine. +// +// This could be fixed by implementing lazy normalization everywhere. +// +// However, we want this to work before then. For that, when checking +// whether a type is Sized we only check that the tails are Sized. As +// PtrBack does not have a tail, we don't need to normalize anything +// and this compiles trait Front { type Back; |
