提交 c5befdc6 编写于 作者: E Eduard-Mihai Burtescu

rustc: always keep an explicit lifetime in trait objects.

上级 41553d6f
...@@ -301,7 +301,7 @@ fn visit_trait_ref(&mut self, t: &'v TraitRef) { ...@@ -301,7 +301,7 @@ fn visit_trait_ref(&mut self, t: &'v TraitRef) {
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
walk_ty_param_bound(self, bounds) walk_ty_param_bound(self, bounds)
} }
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
walk_poly_trait_ref(self, t, m) walk_poly_trait_ref(self, t, m)
} }
fn visit_variant_data(&mut self, fn visit_variant_data(&mut self,
...@@ -421,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v ...@@ -421,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
trait_ref: &'v PolyTraitRef, trait_ref: &'v PolyTraitRef,
_modifier: &'v TraitBoundModifier) _modifier: TraitBoundModifier)
where V: Visitor<'v> where V: Visitor<'v>
{ {
walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
...@@ -566,8 +566,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { ...@@ -566,8 +566,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor.visit_ty(ty); visitor.visit_ty(ty);
visitor.visit_nested_body(length) visitor.visit_nested_body(length)
} }
TyTraitObject(ref bounds) => { TyTraitObject(ref bounds, ref lifetime) => {
walk_list!(visitor, visit_ty_param_bound, bounds); for bound in bounds {
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
}
visitor.visit_lifetime(lifetime);
} }
TyImplTrait(ref bounds) => { TyImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty_param_bound, bounds);
...@@ -695,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ...@@ -695,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) { pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
match *bound { match *bound {
TraitTyParamBound(ref typ, ref modifier) => { TraitTyParamBound(ref typ, modifier) => {
visitor.visit_poly_trait_ref(typ, modifier); visitor.visit_poly_trait_ref(typ, modifier);
} }
RegionTyParamBound(ref lifetime) => { RegionTyParamBound(ref lifetime) => {
......
...@@ -360,7 +360,23 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> { ...@@ -360,7 +360,23 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
hir::TyTypeof(self.record_body(expr, None)) hir::TyTypeof(self.record_body(expr, None))
} }
TyKind::TraitObject(ref bounds) => { TyKind::TraitObject(ref bounds) => {
hir::TyTraitObject(self.lower_bounds(bounds)) let mut lifetime_bound = None;
let bounds = bounds.iter().filter_map(|bound| {
match *bound {
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
Some(self.lower_poly_trait_ref(ty))
}
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
RegionTyParamBound(ref lifetime) => {
lifetime_bound = Some(self.lower_lifetime(lifetime));
None
}
}
}).collect();
let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
self.elided_lifetime(t.span)
});
hir::TyTraitObject(bounds, lifetime_bound)
} }
TyKind::ImplTrait(ref bounds) => { TyKind::ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds)) hir::TyImplTrait(self.lower_bounds(bounds))
...@@ -2361,20 +2377,20 @@ fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> { ...@@ -2361,20 +2377,20 @@ fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
hir::QPath::Resolved(None, path) => { hir::QPath::Resolved(None, path) => {
// Turn trait object paths into `TyTraitObject` instead. // Turn trait object paths into `TyTraitObject` instead.
if let Def::Trait(_) = path.def { if let Def::Trait(_) = path.def {
let principal = hir::TraitTyParamBound(hir::PolyTraitRef { let principal = hir::PolyTraitRef {
bound_lifetimes: hir_vec![], bound_lifetimes: hir_vec![],
trait_ref: hir::TraitRef { trait_ref: hir::TraitRef {
path: path.and_then(|path| path), path: path.and_then(|path| path),
ref_id: id, ref_id: id,
}, },
span, span,
}, hir::TraitBoundModifier::None); };
// The original ID is taken by the `PolyTraitRef`, // The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one. // so the `Ty` itself needs a different one.
id = self.next_id(); id = self.next_id();
hir::TyTraitObject(hir_vec![principal]) hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
} else { } else {
hir::TyPath(hir::QPath::Resolved(None, path)) hir::TyPath(hir::QPath::Resolved(None, path))
} }
......
...@@ -1205,7 +1205,7 @@ pub enum Ty_ { ...@@ -1205,7 +1205,7 @@ pub enum Ty_ {
TyPath(QPath), TyPath(QPath),
/// A trait object type `Bound1 + Bound2 + Bound3` /// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime. /// where `Bound` is a trait or a lifetime.
TyTraitObject(TyParamBounds), TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
/// An `impl Bound1 + Bound2 + Bound3` type /// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime. /// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds), TyImplTrait(TyParamBounds),
......
...@@ -416,8 +416,21 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> { ...@@ -416,8 +416,21 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
hir::TyPath(ref qpath) => { hir::TyPath(ref qpath) => {
self.print_qpath(qpath, false)? self.print_qpath(qpath, false)?
} }
hir::TyTraitObject(ref bounds) => { hir::TyTraitObject(ref bounds, ref lifetime) => {
self.print_bounds("", &bounds[..])?; let mut first = true;
for bound in bounds {
self.nbsp()?;
if first {
first = false;
} else {
self.word_space("+")?;
}
self.print_poly_trait_ref(bound)?;
}
if !lifetime.is_elided() {
self.word_space("+")?;
self.print_lifetime(lifetime)?;
}
} }
hir::TyImplTrait(ref bounds) => { hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?; self.print_bounds("impl ", &bounds[..])?;
......
...@@ -322,6 +322,14 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) { ...@@ -322,6 +322,14 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
intravisit::walk_ty(this, ty); intravisit::walk_ty(this, ty);
}); });
} }
hir::TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds {
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
}
if !lifetime.is_elided() {
self.visit_lifetime(lifetime);
}
}
_ => { _ => {
intravisit::walk_ty(self, ty) intravisit::walk_ty(self, ty)
} }
...@@ -441,7 +449,7 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) { ...@@ -441,7 +449,7 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
fn visit_poly_trait_ref(&mut self, fn visit_poly_trait_ref(&mut self,
trait_ref: &'tcx hir::PolyTraitRef, trait_ref: &'tcx hir::PolyTraitRef,
_modifier: &'tcx hir::TraitBoundModifier) { _modifier: hir::TraitBoundModifier) {
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref); debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() { if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
...@@ -962,7 +970,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) { ...@@ -962,7 +970,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
fn visit_poly_trait_ref(&mut self, fn visit_poly_trait_ref(&mut self,
trait_ref: &hir::PolyTraitRef, trait_ref: &hir::PolyTraitRef,
modifier: &hir::TraitBoundModifier) { modifier: hir::TraitBoundModifier) {
self.binder_depth += 1; self.binder_depth += 1;
intravisit::walk_poly_trait_ref(self, trait_ref, modifier); intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
self.binder_depth -= 1; self.binder_depth -= 1;
......
...@@ -828,7 +828,7 @@ fn visit_ty_param_bound(&mut self, bounds: &'tcx TyParamBound) { ...@@ -828,7 +828,7 @@ fn visit_ty_param_bound(&mut self, bounds: &'tcx TyParamBound) {
visit::walk_ty_param_bound(self, bounds) visit::walk_ty_param_bound(self, bounds)
} }
fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: &'tcx TraitBoundModifier) { fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: TraitBoundModifier) {
debug!("visit_poly_trait_ref: st={:?}", self.st); debug!("visit_poly_trait_ref: st={:?}", self.st);
SawPolyTraitRef.hash(self.st); SawPolyTraitRef.hash(self.st);
m.hash(self.st); m.hash(self.st);
......
...@@ -144,6 +144,17 @@ fn visit_ty(&mut self, ty: &'a Ty) { ...@@ -144,6 +144,17 @@ fn visit_ty(&mut self, ty: &'a Ty) {
}); });
} }
TyKind::TraitObject(ref bounds) => { TyKind::TraitObject(ref bounds) => {
let mut any_lifetime_bounds = false;
for bound in bounds {
if let RegionTyParamBound(ref lifetime) = *bound {
if any_lifetime_bounds {
span_err!(self.session, lifetime.span, E0226,
"only a single explicit lifetime bound is permitted");
break;
}
any_lifetime_bounds = true;
}
}
self.no_questions_in_bounds(bounds, "trait object types", false); self.no_questions_in_bounds(bounds, "trait object types", false);
} }
TyKind::ImplTrait(ref bounds) => { TyKind::ImplTrait(ref bounds) => {
......
...@@ -244,6 +244,7 @@ pub fn foo() {} ...@@ -244,6 +244,7 @@ pub fn foo() {}
} }
register_diagnostics! { register_diagnostics! {
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types E0561, // patterns aren't allowed in function pointer types
E0571, // `break` with a value in a non-`loop`-loop E0571, // `break` with a value in a non-`loop`-loop
......
...@@ -453,24 +453,6 @@ fn convert_parenthesized_parameters(&self, ...@@ -453,24 +453,6 @@ fn convert_parenthesized_parameters(&self,
(self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding) (self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding)
} }
pub fn instantiate_poly_trait_ref(&self,
rscope: &RegionScope,
ast_trait_ref: &hir::PolyTraitRef,
self_ty: Ty<'tcx>,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
let trait_ref = &ast_trait_ref.trait_ref;
let trait_def_id = self.trait_def_id(trait_ref);
self.ast_path_to_poly_trait_ref(rscope,
trait_ref.path.span,
trait_def_id,
self_ty,
trait_ref.ref_id,
trait_ref.path.segments.last().unwrap(),
poly_projections)
}
/// Instantiates the path for the given trait reference, assuming that it's /// Instantiates the path for the given trait reference, assuming that it's
/// bound to a valid trait type. Returns the def_id for the defining trait. /// bound to a valid trait type. Returns the def_id for the defining trait.
/// Fails if the type is a type other than a trait type. /// Fails if the type is a type other than a trait type.
...@@ -505,17 +487,17 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId { ...@@ -505,17 +487,17 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
} }
} }
fn ast_path_to_poly_trait_ref(&self, pub fn instantiate_poly_trait_ref(&self,
rscope: &RegionScope, rscope: &RegionScope,
span: Span, ast_trait_ref: &hir::PolyTraitRef,
trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
path_id: ast::NodeId,
trait_segment: &hir::PathSegment,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>) poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx> -> ty::PolyTraitRef<'tcx>
{ {
debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment); let trait_ref = &ast_trait_ref.trait_ref;
let trait_def_id = self.trait_def_id(trait_ref);
debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
// The trait reference introduces a binding level here, so // The trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could // we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge // do away with this rscope stuff and work this knowledge
...@@ -525,23 +507,23 @@ fn ast_path_to_poly_trait_ref(&self, ...@@ -525,23 +507,23 @@ fn ast_path_to_poly_trait_ref(&self,
let (substs, assoc_bindings) = let (substs, assoc_bindings) =
self.create_substs_for_ast_trait_ref(shifted_rscope, self.create_substs_for_ast_trait_ref(shifted_rscope,
span, trait_ref.path.span,
trait_def_id, trait_def_id,
self_ty, self_ty,
trait_segment); trait_ref.path.segments.last().unwrap());
let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs)); let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
// specify type to assert that error was already reported in Err case: // specify type to assert that error was already reported in Err case:
let predicate: Result<_, ErrorReported> = let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate(path_id, self.ast_type_binding_to_poly_projection_predicate(trait_ref.ref_id,
poly_trait_ref, poly_trait_ref,
binding); binding);
predicate.ok() // ok to ignore Err() because ErrorReported (see above) predicate.ok() // ok to ignore Err() because ErrorReported (see above)
})); }));
debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}", debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
trait_segment, poly_projections, poly_trait_ref); trait_ref, poly_projections, poly_trait_ref);
poly_trait_ref poly_trait_ref
} }
...@@ -754,32 +736,29 @@ fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) ...@@ -754,32 +736,29 @@ fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
} }
fn trait_path_to_object_type(&self, fn conv_object_ty_poly_trait_ref(&self,
rscope: &RegionScope, rscope: &RegionScope,
path_span: Span,
trait_def_id: DefId,
trait_path_ref_id: ast::NodeId,
trait_segment: &hir::PathSegment,
span: Span, span: Span,
partitioned_bounds: PartitionedBounds) trait_bounds: &[hir::PolyTraitRef],
-> Ty<'tcx> { lifetime: &hir::Lifetime)
-> Ty<'tcx>
{
let tcx = self.tcx(); let tcx = self.tcx();
if trait_bounds.is_empty() {
span_err!(tcx.sess, span, E0224,
"at least one non-builtin trait is required for an object type");
return tcx.types.err;
}
let mut projection_bounds = vec![]; let mut projection_bounds = vec![];
let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF); let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
let principal = self.ast_path_to_poly_trait_ref(rscope, let principal = self.instantiate_poly_trait_ref(rscope,
path_span, &trait_bounds[0],
trait_def_id,
dummy_self, dummy_self,
trait_path_ref_id,
trait_segment,
&mut projection_bounds); &mut projection_bounds);
let PartitionedBounds { trait_bounds, let (auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
region_bounds } =
partitioned_bounds;
let (auto_traits, trait_bounds) = split_auto_traits(tcx, trait_bounds);
if !trait_bounds.is_empty() { if !trait_bounds.is_empty() {
let b = &trait_bounds[0]; let b = &trait_bounds[0];
...@@ -854,13 +833,12 @@ fn trait_path_to_object_type(&self, ...@@ -854,13 +833,12 @@ fn trait_path_to_object_type(&self,
v.sort_by(|a, b| a.cmp(tcx, b)); v.sort_by(|a, b| a.cmp(tcx, b));
let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter())); let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter()));
let region_bound = self.compute_object_lifetime_bound(span,
&region_bounds,
existential_predicates);
let region_bound = match region_bound { // Explicitly specified region bound. Use that.
Some(r) => r, let region_bound = if !lifetime.is_elided() {
None => { self.ast_region_to_region(lifetime, None)
} else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
tcx.mk_region(match rscope.object_lifetime_default(span) { tcx.mk_region(match rscope.object_lifetime_default(span) {
Some(r) => r, Some(r) => r,
None => { None => {
...@@ -870,7 +848,7 @@ fn trait_path_to_object_type(&self, ...@@ -870,7 +848,7 @@ fn trait_path_to_object_type(&self,
ty::ReStatic ty::ReStatic
} }
}) })
} })
}; };
debug!("region_bound: {:?}", region_bound); debug!("region_bound: {:?}", region_bound);
...@@ -1330,8 +1308,8 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> { ...@@ -1330,8 +1308,8 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
} }
tcx.mk_fn_ptr(bare_fn_ty) tcx.mk_fn_ptr(bare_fn_ty)
} }
hir::TyTraitObject(ref bounds) => { hir::TyTraitObject(ref bounds, ref lifetime) => {
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds) self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds, lifetime)
} }
hir::TyImplTrait(ref bounds) => { hir::TyImplTrait(ref bounds) => {
use collect::{compute_bounds, SizedByDefault}; use collect::{compute_bounds, SizedByDefault};
...@@ -1537,33 +1515,6 @@ pub fn ty_of_closure(&self, ...@@ -1537,33 +1515,6 @@ pub fn ty_of_closure(&self,
} }
} }
fn conv_object_ty_poly_trait_ref(&self,
rscope: &RegionScope,
span: Span,
ast_bounds: &[hir::TyParamBound])
-> Ty<'tcx>
{
let mut partitioned_bounds = partition_bounds(ast_bounds);
let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
partitioned_bounds.trait_bounds.remove(0)
} else {
span_err!(self.tcx().sess, span, E0224,
"at least one non-builtin trait is required for an object type");
return self.tcx().types.err;
};
let trait_ref = &trait_bound.trait_ref;
let trait_def_id = self.trait_def_id(trait_ref);
self.trait_path_to_object_type(rscope,
trait_ref.path.span,
trait_def_id,
trait_ref.ref_id,
trait_ref.path.segments.last().unwrap(),
span,
partitioned_bounds)
}
/// Given the bounds on an object, determines what single region bound (if any) we can /// Given the bounds on an object, determines what single region bound (if any) we can
/// use to summarize this type. The basic idea is that we will use the bound the user /// use to summarize this type. The basic idea is that we will use the bound the user
/// provided, if they provided one, and otherwise search the supertypes of trait bounds /// provided, if they provided one, and otherwise search the supertypes of trait bounds
...@@ -1571,27 +1522,14 @@ fn conv_object_ty_poly_trait_ref(&self, ...@@ -1571,27 +1522,14 @@ fn conv_object_ty_poly_trait_ref(&self,
/// we return `None`. /// we return `None`.
fn compute_object_lifetime_bound(&self, fn compute_object_lifetime_bound(&self,
span: Span, span: Span,
explicit_region_bounds: &[&hir::Lifetime],
existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>) existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
-> Option<&'tcx ty::Region> // if None, use the default -> Option<&'tcx ty::Region> // if None, use the default
{ {
let tcx = self.tcx(); let tcx = self.tcx();
debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \ debug!("compute_opt_region_bound(existential_predicates={:?})",
existential_predicates={:?})",
explicit_region_bounds,
existential_predicates); existential_predicates);
if explicit_region_bounds.len() > 1 {
span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
"only a single explicit lifetime bound is permitted");
}
if let Some(&r) = explicit_region_bounds.get(0) {
// Explicitly specified region bound. Use that.
return Some(self.ast_region_to_region(r, None));
}
if let Some(principal) = existential_predicates.principal() { if let Some(principal) = existential_predicates.principal() {
if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) { if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
return Some(tcx.mk_region(ty::ReStatic)); return Some(tcx.mk_region(ty::ReStatic));
...@@ -1627,18 +1565,13 @@ fn compute_object_lifetime_bound(&self, ...@@ -1627,18 +1565,13 @@ fn compute_object_lifetime_bound(&self,
} }
} }
pub struct PartitionedBounds<'a> {
pub trait_bounds: Vec<&'a hir::PolyTraitRef>,
pub region_bounds: Vec<&'a hir::Lifetime>,
}
/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the /// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the
/// remaining general trait bounds. /// remaining general trait bounds.
fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_bounds: Vec<&'b hir::PolyTraitRef>) trait_bounds: &'b [hir::PolyTraitRef])
-> (Vec<DefId>, Vec<&'b hir::PolyTraitRef>) -> (Vec<DefId>, Vec<&'b hir::PolyTraitRef>)
{ {
let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.into_iter().partition(|bound| { let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| {
match bound.trait_ref.path.def { match bound.trait_ref.path.def {
Def::Trait(trait_did) => { Def::Trait(trait_did) => {
// Checks whether `trait_did` refers to one of the builtin // Checks whether `trait_did` refers to one of the builtin
...@@ -1675,30 +1608,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ...@@ -1675,30 +1608,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
(auto_traits, trait_bounds) (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 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) => {
trait_bounds.push(b);
}
hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
hir::RegionTyParamBound(ref l) => {
region_bounds.push(l);
}
}
}
PartitionedBounds {
trait_bounds: trait_bounds,
region_bounds: region_bounds,
}
}
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
ty_param_defs: &[ty::TypeParameterDef]) { ty_param_defs: &[ty::TypeParameterDef]) {
let accepted = ty_param_defs.len(); let accepted = ty_param_defs.len();
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
*/ */
use astconv::{AstConv, Bounds, PartitionedBounds, partition_bounds}; use astconv::{AstConv, Bounds};
use lint; use lint;
use constrained_type_params as ctp; use constrained_type_params as ctp;
use middle::lang_items::SizedTraitLangItem; use middle::lang_items::SizedTraitLangItem;
...@@ -1961,10 +1961,19 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, ...@@ -1961,10 +1961,19 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
span: Span) span: Span)
-> Bounds<'tcx> -> Bounds<'tcx>
{ {
let PartitionedBounds { let mut region_bounds = vec![];
trait_bounds, let mut trait_bounds = vec![];
region_bounds for ast_bound in ast_bounds {
} = partition_bounds(&ast_bounds); match *ast_bound {
hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
trait_bounds.push(b);
}
hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
hir::RegionTyParamBound(ref l) => {
region_bounds.push(l);
}
}
}
let mut projection_bounds = vec![]; let mut projection_bounds = vec![];
......
...@@ -4096,7 +4096,6 @@ fn main() { ...@@ -4096,7 +4096,6 @@ fn main() {
// E0222, // Error code E0045 (variadic function must have C calling // E0222, // Error code E0045 (variadic function must have C calling
// convention) duplicate // convention) duplicate
E0224, // at least one non-builtin train is required for an object type E0224, // at least one non-builtin train is required for an object type
E0226, // only a single explicit lifetime bound is permitted
E0227, // ambiguous lifetime bound, explicit lifetime bound required E0227, // ambiguous lifetime bound, explicit lifetime bound required
E0228, // explicit lifetime bound required E0228, // explicit lifetime bound required
E0231, // only named substitution parameters are allowed E0231, // only named substitution parameters are allowed
......
...@@ -1776,15 +1776,18 @@ fn clean(&self, cx: &DocContext) -> Type { ...@@ -1776,15 +1776,18 @@ fn clean(&self, cx: &DocContext) -> Type {
trait_: box resolve_type(cx, trait_path.clean(cx), self.id) trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
} }
} }
TyTraitObject(ref bounds) => { TyTraitObject(ref bounds, ref lifetime) => {
let lhs_ty = bounds[0].clean(cx); match bounds[0].clean(cx).trait_ {
match lhs_ty {
TraitBound(poly_trait, ..) => {
match poly_trait.trait_ {
ResolvedPath { path, typarams: None, did, is_generic } => { ResolvedPath { path, typarams: None, did, is_generic } => {
let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| {
TraitBound(bound.clean(cx), hir::TraitBoundModifier::None)
}).collect();
if !lifetime.is_elided() {
bounds.push(RegionBound(lifetime.clean(cx)));
}
ResolvedPath { ResolvedPath {
path: path, path: path,
typarams: Some(bounds[1..].clean(cx)), typarams: Some(bounds),
did: did, did: did,
is_generic: is_generic, is_generic: is_generic,
} }
...@@ -1792,9 +1795,6 @@ fn clean(&self, cx: &DocContext) -> Type { ...@@ -1792,9 +1795,6 @@ fn clean(&self, cx: &DocContext) -> Type {
_ => Infer // shouldn't happen _ => Infer // shouldn't happen
} }
} }
_ => Infer // shouldn't happen
}
}
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)), TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
TyInfer => Infer, TyInfer => Infer,
......
...@@ -18,7 +18,7 @@ trait SomeTrait { } ...@@ -18,7 +18,7 @@ trait SomeTrait { }
// Bounds on object types: // Bounds on object types:
struct Foo<'a,'b,'c> { struct Foo<'a,'b,'c> { //~ ERROR parameter `'b` is never used
// All of these are ok, because we can derive exactly one bound: // All of these are ok, because we can derive exactly one bound:
a: Box<IsStatic>, a: Box<IsStatic>,
b: Box<Is<'static>>, b: Box<Is<'static>>,
...@@ -28,7 +28,9 @@ struct Foo<'a,'b,'c> { ...@@ -28,7 +28,9 @@ struct Foo<'a,'b,'c> {
f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599. f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599.
g: Box<SomeTrait+'a>, g: Box<SomeTrait+'a>,
z: Box<Is<'a>+'b+'c>, //~ ERROR only a single explicit lifetime bound is permitted z: Box<Is<'a>+'b+'c>,
//~^ ERROR only a single explicit lifetime bound is permitted
//~| ERROR lifetime bound not satisfied
} }
fn test< fn test<
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册