From fcc23238fd40c568cf3f7e1a2947ebb93277091e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Jan 2015 11:40:35 -0500 Subject: [PATCH 01/69] Be stricter with binders in method probing. --- src/librustc/middle/ty.rs | 15 ++++++ src/librustc_typeck/check/method/probe.rs | 57 +++++++++++++---------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c359233eca173..4ccb399c17cf4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1077,6 +1077,12 @@ pub struct FnSig<'tcx> { pub type PolyFnSig<'tcx> = Binder>; +impl<'tcx> PolyFnSig<'tcx> { + pub fn input(&self, index: uint) -> ty::Binder> { + ty::Binder(self.0.inputs[index]) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Show)] pub struct ParamTy { pub space: subst::ParamSpace, @@ -1464,10 +1470,12 @@ impl<'tcx> PolyTraitRef<'tcx> { } pub fn substs(&self) -> &'tcx Substs<'tcx> { + // TODO every use of this fn is probably a bug, it should yield Binder<> self.0.substs } pub fn input_types(&self) -> &[Ty<'tcx>] { + // TODO every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } @@ -6950,6 +6958,13 @@ impl<'tcx> RegionEscape for Ty<'tcx> { } } +impl<'tcx> RegionEscape for Substs<'tcx> { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { + self.types.has_regions_escaping_depth(depth) || + self.regions.has_regions_escaping_depth(depth) + } +} + impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace { fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.iter_enumerated().any(|(space, _, t)| { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 115711ae92b29..6f2bbb7df2bf1 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -18,7 +18,7 @@ use middle::fast_reject; use middle::subst; use middle::subst::Subst; use middle::traits; -use middle::ty::{self, Ty, ToPolyTraitRef}; +use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef}; use middle::ty_fold::TypeFoldable; use middle::infer; use middle::infer::InferCtxt; @@ -309,18 +309,20 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // argument type like `&Trait`. let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty); self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| { + let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); + let vtable_index = traits::get_vtable_index_of_object_method(tcx, trait_ref.clone(), - new_trait_ref.def_id(), + new_trait_ref.def_id, method_num); - let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs()); + let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs); this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, method_ty: m, - kind: ObjectCandidate(new_trait_ref.def_id(), method_num, vtable_index) + kind: ObjectCandidate(new_trait_ref.def_id, method_num, vtable_index) }); }); } @@ -353,34 +355,37 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }) .collect(); - self.elaborate_bounds(bounds.as_slice(), true, |this, trait_ref, m, method_num| { + self.elaborate_bounds(bounds.as_slice(), true, |this, poly_trait_ref, m, method_num| { + let trait_ref = + this.erase_late_bound_regions(&poly_trait_ref); + let xform_self_ty = - this.xform_self_ty(&m, trait_ref.substs()); + this.xform_self_ty(&m, trait_ref.substs); debug!("found match: trait_ref={} substs={} m={}", trait_ref.repr(this.tcx()), - trait_ref.substs().repr(this.tcx()), + trait_ref.substs.repr(this.tcx()), m.repr(this.tcx())); assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(), - trait_ref.substs().types.get_slice(subst::TypeSpace).len()); + trait_ref.substs.types.get_slice(subst::TypeSpace).len()); assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(), - trait_ref.substs().regions().get_slice(subst::TypeSpace).len()); + trait_ref.substs.regions().get_slice(subst::TypeSpace).len()); assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(), - trait_ref.substs().types.get_slice(subst::SelfSpace).len()); + trait_ref.substs.types.get_slice(subst::SelfSpace).len()); assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(), - trait_ref.substs().regions().get_slice(subst::SelfSpace).len()); + trait_ref.substs.regions().get_slice(subst::SelfSpace).len()); // Because this trait derives from a where-clause, it // should not contain any inference variables or other // artifacts. This means it is safe to put into the // `WhereClauseCandidate` and (eventually) into the // `WhereClausePick`. - assert!(trait_ref.substs().types.iter().all(|&t| !ty::type_needs_infer(t))); + assert!(trait_ref.substs.types.iter().all(|&t| !ty::type_needs_infer(t))); this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, method_ty: m, - kind: WhereClauseCandidate(trait_ref, method_num) + kind: WhereClauseCandidate(poly_trait_ref, method_num) }); }); } @@ -614,11 +619,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // Check whether there are any where-clauses pertaining to this trait. let caller_predicates = self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec(); - for bound in traits::elaborate_predicates(self.tcx(), caller_predicates) - .filter_map(|p| p.to_opt_poly_trait_ref()) - .filter(|b| b.def_id() == trait_def_id) + for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates) + .filter_map(|p| p.to_opt_poly_trait_ref()) + .filter(|b| b.def_id() == trait_def_id) { - let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs()); + let bound = self.erase_late_bound_regions(&poly_bound); + let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs); debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}", bound.repr(self.tcx()), @@ -627,7 +633,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.extension_candidates.push(Candidate { xform_self_ty: xform_self_ty, method_ty: method_ty.clone(), - kind: WhereClauseCandidate(bound, method_index) + kind: WhereClauseCandidate(poly_bound, method_index) }); } } @@ -920,6 +926,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { method.fty.sig.0.inputs[0].repr(self.tcx()), substs.repr(self.tcx())); + assert!(!substs.has_escaping_regions()); + // It is possible for type parameters or early-bound lifetimes // to appear in the signature of `self`. The substitutions we // are given do not include type/lifetime parameters for the @@ -949,14 +957,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { substs = &placeholder; } - // Replace early-bound regions and types. - let xform_self_ty = method.fty.sig.0.inputs[0].subst(self.tcx(), substs); + // Erase any late-bound regions from the method and substitute + // in the values from the substitution. + let xform_self_ty = method.fty.sig.input(0); + let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); + let xform_self_ty = xform_self_ty.subst(self.tcx(), substs); - // Replace late-bound regions bound in the impl or - // where-clause (2 levels of binding) and method (1 level of binding). - self.erase_late_bound_regions( - &self.erase_late_bound_regions( - &ty::Binder(ty::Binder(xform_self_ty)))) + xform_self_ty } fn impl_substs(&self, From 279de38cc8d1c1a1c68d714b9384da32c240e420 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 5 Jan 2015 21:50:01 -0500 Subject: [PATCH 02/69] Support methods invoked on projection types based on the bounds found in the trait. --- src/librustc/middle/infer/combine.rs | 10 +++ src/librustc/middle/infer/mod.rs | 33 ++++++---- src/librustc/middle/subst.rs | 2 +- src/librustc/middle/traits/project.rs | 2 +- src/librustc/middle/traits/select.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 74 ++++++++++++++++++++- src/test/run-pass/method-projection.rs | 78 +++++++++++++++++++++++ 7 files changed, 185 insertions(+), 16 deletions(-) create mode 100644 src/test/run-pass/method-projection.rs diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index dd711fcbf022e..772d7b2532a7b 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -427,6 +427,16 @@ impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> { } } +impl<'tcx> Combineable<'tcx> for Ty<'tcx> { + fn combine>(combiner: &C, + a: &Ty<'tcx>, + b: &Ty<'tcx>) + -> cres<'tcx, Ty<'tcx>> + { + combiner.tys(*a, *b) + } +} + impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> { fn combine>(combiner: &C, a: &ty::ProjectionPredicate<'tcx>, diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index c2db81d311483..05b8d9da06fe5 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -39,7 +39,7 @@ use util::ppaux::{ty_to_string}; use util::ppaux::{Repr, UserString}; use self::coercion::Coerce; -use self::combine::{Combine, CombineFields}; +use self::combine::{Combine, Combineable, CombineFields}; use self::region_inference::{RegionVarBindings, RegionSnapshot}; use self::equate::Equate; use self::sub::Sub; @@ -360,17 +360,9 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, }) } -pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, - a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> { - debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx)); - cx.probe(|_| { - let trace = TypeTrace { - origin: Misc(codemap::DUMMY_SP), - values: Types(expected_found(true, a, b)) - }; - cx.equate(true, trace).tys(a, b) - }).to_ures() +pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> ures<'tcx> +{ + cx.can_equate(&a, &b) } pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, @@ -1072,6 +1064,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.region_vars.verify_generic_bound(origin, kind, a, bs); } + + pub fn can_equate(&self, a: &T, b: &T) -> ures<'tcx> + where T : Combineable<'tcx> + Repr<'tcx> + { + debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx)); + self.probe(|_| { + // Gin up a dummy trace, since this won't be committed + // anyhow. We should make this typetrace stuff more + // generic so we don't have to do anything quite this + // terrible. + let e = self.tcx.types.err; + let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP), + values: Types(expected_found(true, e, e)) }; + let eq = self.equate(true, trace); + Combineable::combine(&eq, a, b) + }).to_ures() + } } impl<'tcx> TypeTrace<'tcx> { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index cd29ce28ac174..5227dc0a83a7d 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -394,7 +394,7 @@ impl VecPerParamSpace { self.content.as_slice() } - pub fn to_vec(self) -> Vec { + pub fn into_vec(self) -> Vec { self.content } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 65f7ad296db51..df246a9ed4173 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -641,7 +641,7 @@ fn confirm_candidate<'cx,'tcx>( } match impl_ty { - Some(ty) => (ty, impl_vtable.nested.to_vec()), + Some(ty) => (ty, impl_vtable.nested.into_vec()), None => { // This means that the impl is missing a // definition for the associated type. This error diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 2393b7d733d00..cdd040a7bc69b 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -835,7 +835,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bounds.repr(self.tcx())); let matching_bound = - util::elaborate_predicates(self.tcx(), bounds.predicates.to_vec()) + util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec()) .filter_to_traits() .find( |bound| self.infcx.probe( diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 6f2bbb7df2bf1..d7a42b59a123b 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -62,6 +62,7 @@ enum CandidateKind<'tcx> { subst::Substs<'tcx>, MethodIndex), UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex), WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex), + ProjectionCandidate(ast::DefId, MethodIndex), } pub struct Pick<'tcx> { @@ -479,6 +480,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { method.clone(), matching_index); + self.assemble_projection_candidates(trait_def_id, + method.clone(), + matching_index); + self.assemble_where_clause_candidates(trait_def_id, method, matching_index); @@ -608,6 +613,64 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } } + fn assemble_projection_candidates(&mut self, + trait_def_id: ast::DefId, + method: Rc>, + method_index: uint) + { + debug!("assemble_projection_candidates(\ + trait_def_id={}, \ + method={}, \ + method_index={})", + trait_def_id.repr(self.tcx()), + method.repr(self.tcx()), + method_index); + + for step in self.steps.iter() { + debug!("assemble_projection_candidates: step={}", + step.repr(self.tcx())); + + let projection_trait_ref = match step.self_ty.sty { + ty::ty_projection(ref data) => &data.trait_ref, + _ => continue, + }; + + debug!("assemble_projection_candidates: projection_trait_ref={}", + projection_trait_ref.repr(self.tcx())); + + let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id); + let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs); + let predicates = bounds.predicates.into_vec(); + debug!("assemble_projection_candidates: predicates={}", + predicates.repr(self.tcx())); + for poly_bound in + traits::elaborate_predicates(self.tcx(), predicates) + .filter_map(|p| p.to_opt_poly_trait_ref()) // TODO filter_to_traits() + .filter(|b| b.def_id() == trait_def_id) + { + let bound = self.erase_late_bound_regions(&poly_bound); + + debug!("assemble_projection_candidates: projection_trait_ref={} bound={}", + projection_trait_ref.repr(self.tcx()), + bound.repr(self.tcx())); + + if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() { + let xform_self_ty = self.xform_self_ty(&method, bound.substs); + + debug!("assemble_projection_candidates: bound={} xform_self_ty={}", + bound.repr(self.tcx()), + xform_self_ty.repr(self.tcx())); + + self.extension_candidates.push(Candidate { + xform_self_ty: xform_self_ty, + method_ty: method.clone(), + kind: ProjectionCandidate(trait_def_id, method_index) + }); + } + } + } + } + fn assemble_where_clause_candidates(&mut self, trait_def_id: ast::DefId, method_ty: Rc>, @@ -616,7 +679,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { debug!("assemble_where_clause_candidates(trait_def_id={})", trait_def_id.repr(self.tcx())); - // Check whether there are any where-clauses pertaining to this trait. let caller_predicates = self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec(); for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates) @@ -835,6 +897,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { norm_obligations.iter().all(|o| selcx.evaluate_obligation(o)) } + ProjectionCandidate(..) | ObjectCandidate(..) | UnboxedClosureCandidate(..) | WhereClauseCandidate(..) => { @@ -1072,6 +1135,9 @@ impl<'tcx> Candidate<'tcx> { WhereClausePick((*trait_ref).clone(), index) } + ProjectionCandidate(def_id, index) => { + TraitPick(def_id, index) + } } } } @@ -1083,6 +1149,7 @@ impl<'tcx> Candidate<'tcx> { ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id), UnboxedClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id), WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()), + ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id), } } @@ -1101,6 +1168,9 @@ impl<'tcx> Candidate<'tcx> { WhereClauseCandidate(ref trait_ref, method_num) => { Some((trait_ref.def_id(), method_num)) } + ProjectionCandidate(trait_def_id, method_num) => { + Some((trait_def_id, method_num)) + } } } } @@ -1127,6 +1197,8 @@ impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> { format!("UnboxedClosureCandidate({},{})", a.repr(tcx), b), WhereClauseCandidate(ref a, ref b) => format!("WhereClauseCandidate({},{})", a.repr(tcx), b), + ProjectionCandidate(ref a, ref b) => + format!("ProjectionCandidate({},{})", a.repr(tcx), b), } } } diff --git a/src/test/run-pass/method-projection.rs b/src/test/run-pass/method-projection.rs new file mode 100644 index 0000000000000..6f72a163981c9 --- /dev/null +++ b/src/test/run-pass/method-projection.rs @@ -0,0 +1,78 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we can use method notation to call methods based on a +// projection bound from a trait. Issue #20469. + +/////////////////////////////////////////////////////////////////////////// + +trait MakeString { + fn make_string(&self) -> String; +} + +impl MakeString for int { + fn make_string(&self) -> String { + format!("{}", *self) + } +} + +impl MakeString for uint { + fn make_string(&self) -> String { + format!("{}", *self) + } +} + +/////////////////////////////////////////////////////////////////////////// + +trait Foo { + type F: MakeString; + + fn get(&self) -> &Self::F; +} + +fn foo(f: &F) -> String { + f.get().make_string() +} + +/////////////////////////////////////////////////////////////////////////// + +struct SomeStruct { + field: int, +} + +impl Foo for SomeStruct { + type F = int; + + fn get(&self) -> &int { + &self.field + } +} + +/////////////////////////////////////////////////////////////////////////// + +struct SomeOtherStruct { + field: uint, +} + +impl Foo for SomeOtherStruct { + type F = uint; + + fn get(&self) -> &uint { + &self.field + } +} + +fn main() { + let x = SomeStruct { field: 22 }; + assert_eq!(foo(&x), format!("22")); + + let x = SomeOtherStruct { field: 44 }; + assert_eq!(foo(&x), format!("44")); +} From 3f1cf328b3d7c21d4e43f2a90cd7e83fb863b81f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Jan 2015 17:32:43 -0500 Subject: [PATCH 03/69] Convert the TODO into FIXME. --- src/librustc/middle/ty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 4ccb399c17cf4..b07315605e467 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1470,12 +1470,12 @@ impl<'tcx> PolyTraitRef<'tcx> { } pub fn substs(&self) -> &'tcx Substs<'tcx> { - // TODO every use of this fn is probably a bug, it should yield Binder<> + // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.substs } pub fn input_types(&self) -> &[Ty<'tcx>] { - // TODO every use of this fn is probably a bug, it should yield Binder<> + // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } From ab02f9e42a15f359bc3c732311deee678fe2485d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Jan 2015 17:53:14 -0500 Subject: [PATCH 04/69] Workaround privacy bug or something else; filter_to_traits() fails to link, but this does the same thing. --- src/librustc_typeck/check/method/probe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index d7a42b59a123b..1634b47988df4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -645,7 +645,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { predicates.repr(self.tcx())); for poly_bound in traits::elaborate_predicates(self.tcx(), predicates) - .filter_map(|p| p.to_opt_poly_trait_ref()) // TODO filter_to_traits() + .filter_map(|p| p.to_opt_poly_trait_ref()) .filter(|b| b.def_id() == trait_def_id) { let bound = self.erase_late_bound_regions(&poly_bound); From 1bc3c960f4a803007ceb74b9085d15c61a88de11 Mon Sep 17 00:00:00 2001 From: Hyeon Kim Date: Tue, 6 Jan 2015 11:18:32 +0900 Subject: [PATCH 05/69] Correct the comment of the function `llsize_of_real` Consult the issue #20460 --- src/librustc_trans/trans/machine.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/trans/machine.rs b/src/librustc_trans/trans/machine.rs index 41738f1e58f3e..95d67cd54c124 100644 --- a/src/librustc_trans/trans/machine.rs +++ b/src/librustc_trans/trans/machine.rs @@ -43,8 +43,10 @@ pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize { // Returns, as near as we can figure, the "real" size of a type. As in, the // bits in this number of bytes actually carry data related to the datum -// with the type. Not junk, padding, accidentally-damaged words, or -// whatever. Rounds up to the nearest byte though, so if you have a 1-bit +// with the type. Not junk, accidentally-damaged words, or whatever. +// Note that padding of the type will be included for structs, but not for the +// other types (i.e. SIMD types). +// Rounds up to the nearest byte though, so if you have a 1-bit // value, we return 1 here, not 0. Most of rustc works in bytes. Be warned // that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value // at the codegen level! In general you should prefer `llbitsize_of_real` From 9041e6e0eede9e04a743a4ef6c26f13b767ef970 Mon Sep 17 00:00:00 2001 From: Hyeon Kim Date: Mon, 5 Jan 2015 12:59:47 +0900 Subject: [PATCH 06/69] Let `size_of` always be multiple of `min_align_of` This change fixes the issue #20460 --- src/librustc_trans/trans/intrinsic.rs | 2 +- src/test/run-pass/simd-size-align.rs | 70 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/simd-size-align.rs diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 6e71653891181..1ce67f7934ad7 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -311,7 +311,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "size_of") => { let tp_ty = *substs.types.get(FnSpace, 0); let lltp_ty = type_of::type_of(ccx, tp_ty); - C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty)) + C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty)) } (_, "min_align_of") => { let tp_ty = *substs.types.get(FnSpace, 0); diff --git a/src/test/run-pass/simd-size-align.rs b/src/test/run-pass/simd-size-align.rs new file mode 100644 index 0000000000000..582810f0def33 --- /dev/null +++ b/src/test/run-pass/simd-size-align.rs @@ -0,0 +1,70 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(simd)] +#![allow(non_camel_case_types)] + +use std::mem; + +/// `T` should satisfy `size_of T (mod min_align_of T) === 0` to be stored at `Vec` properly +/// Please consult the issue #20460 +fn check() { + assert_eq!(mem::size_of::() % mem::min_align_of::(), 0) +} + +fn main() { + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); + + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); + + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); + check::(); +} + +#[simd] struct u8x2(u8, u8); +#[simd] struct u8x3(u8, u8, u8); +#[simd] struct u8x4(u8, u8, u8, u8); +#[simd] struct u8x5(u8, u8, u8, u8, u8); +#[simd] struct u8x6(u8, u8, u8, u8, u8, u8); +#[simd] struct u8x7(u8, u8, u8, u8, u8, u8, u8); +#[simd] struct u8x8(u8, u8, u8, u8, u8, u8, u8, u8); + +#[simd] struct i16x2(i16, i16); +#[simd] struct i16x3(i16, i16, i16); +#[simd] struct i16x4(i16, i16, i16, i16); +#[simd] struct i16x5(i16, i16, i16, i16, i16); +#[simd] struct i16x6(i16, i16, i16, i16, i16, i16); +#[simd] struct i16x7(i16, i16, i16, i16, i16, i16, i16); +#[simd] struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); + +#[simd] struct f32x2(f32, f32); +#[simd] struct f32x3(f32, f32, f32); +#[simd] struct f32x4(f32, f32, f32, f32); +#[simd] struct f32x5(f32, f32, f32, f32, f32); +#[simd] struct f32x6(f32, f32, f32, f32, f32, f32); +#[simd] struct f32x7(f32, f32, f32, f32, f32, f32, f32); +#[simd] struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); From da83e4d98a494d81be10d3f3da94841a1fe29ae1 Mon Sep 17 00:00:00 2001 From: FakeKane Date: Wed, 7 Jan 2015 09:09:37 -0500 Subject: [PATCH 07/69] oboe removed --- src/doc/intro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/intro.md b/src/doc/intro.md index a4e9d85bffdf8..8c7409d2fb3a4 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -543,7 +543,7 @@ use std::thread::Thread; fn main() { let vec = vec![1i, 2, 3]; - for i in range(1u, 3) { + for i in range(0u, 3) { Thread::spawn(move || { println!("{}", vec[i]); }).detach(); @@ -559,7 +559,7 @@ a vector: ```{rust} let vec = vec![1i, 2, 3]; -for i in range(1u, vec.len()) { +for i in range(0u, vec.len()) { println!("{}", vec[i]); } ``` From 4f801c433f0f48fcdbe7e63575d4ac131774400e Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 7 Jan 2015 09:23:31 -0500 Subject: [PATCH 08/69] Bump copyright year in doc footer --- src/doc/footer.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/footer.inc b/src/doc/footer.inc index 4e7d60586f23d..f32f2fd443f8e 100644 --- a/src/doc/footer.inc +++ b/src/doc/footer.inc @@ -1,5 +1,5 @@