mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
rustc: always keep an explicit lifetime in trait objects.
This commit is contained in:
parent
41553d6fbc
commit
c5befdc630
@ -301,7 +301,7 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
|
||||
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)
|
||||
}
|
||||
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
|
||||
|
||||
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
|
||||
trait_ref: &'v PolyTraitRef,
|
||||
_modifier: &'v TraitBoundModifier)
|
||||
_modifier: TraitBoundModifier)
|
||||
where V: Visitor<'v>
|
||||
{
|
||||
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) {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_nested_body(length)
|
||||
}
|
||||
TyTraitObject(ref bounds) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
TyTraitObject(ref bounds, ref lifetime) => {
|
||||
for bound in bounds {
|
||||
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
|
||||
}
|
||||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
TyImplTrait(ref 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
|
||||
|
||||
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref typ, ref modifier) => {
|
||||
TraitTyParamBound(ref typ, modifier) => {
|
||||
visitor.visit_poly_trait_ref(typ, modifier);
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
|
@ -360,7 +360,23 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::TyTypeof(self.record_body(expr, None))
|
||||
}
|
||||
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) => {
|
||||
hir::TyImplTrait(self.lower_bounds(bounds))
|
||||
@ -2361,20 +2377,20 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::QPath::Resolved(None, path) => {
|
||||
// Turn trait object paths into `TyTraitObject` instead.
|
||||
if let Def::Trait(_) = path.def {
|
||||
let principal = hir::TraitTyParamBound(hir::PolyTraitRef {
|
||||
let principal = hir::PolyTraitRef {
|
||||
bound_lifetimes: hir_vec![],
|
||||
trait_ref: hir::TraitRef {
|
||||
path: path.and_then(|path| path),
|
||||
ref_id: id,
|
||||
},
|
||||
span,
|
||||
}, hir::TraitBoundModifier::None);
|
||||
};
|
||||
|
||||
// The original ID is taken by the `PolyTraitRef`,
|
||||
// so the `Ty` itself needs a different one.
|
||||
id = self.next_id();
|
||||
|
||||
hir::TyTraitObject(hir_vec![principal])
|
||||
hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
|
||||
} else {
|
||||
hir::TyPath(hir::QPath::Resolved(None, path))
|
||||
}
|
||||
|
@ -1205,7 +1205,7 @@ pub enum Ty_ {
|
||||
TyPath(QPath),
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TyTraitObject(TyParamBounds),
|
||||
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
|
||||
/// An `impl Bound1 + Bound2 + Bound3` type
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TyImplTrait(TyParamBounds),
|
||||
|
@ -416,8 +416,21 @@ impl<'a> State<'a> {
|
||||
hir::TyPath(ref qpath) => {
|
||||
self.print_qpath(qpath, false)?
|
||||
}
|
||||
hir::TyTraitObject(ref bounds) => {
|
||||
self.print_bounds("", &bounds[..])?;
|
||||
hir::TyTraitObject(ref bounds, ref lifetime) => {
|
||||
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) => {
|
||||
self.print_bounds("impl ", &bounds[..])?;
|
||||
|
@ -322,6 +322,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
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)
|
||||
}
|
||||
@ -441,7 +449,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
|
||||
fn visit_poly_trait_ref(&mut self,
|
||||
trait_ref: &'tcx hir::PolyTraitRef,
|
||||
_modifier: &'tcx hir::TraitBoundModifier) {
|
||||
_modifier: hir::TraitBoundModifier) {
|
||||
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
|
||||
|
||||
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
|
||||
@ -962,7 +970,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
|
||||
fn visit_poly_trait_ref(&mut self,
|
||||
trait_ref: &hir::PolyTraitRef,
|
||||
modifier: &hir::TraitBoundModifier) {
|
||||
modifier: hir::TraitBoundModifier) {
|
||||
self.binder_depth += 1;
|
||||
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
|
||||
self.binder_depth -= 1;
|
||||
|
@ -828,7 +828,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
|
||||
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);
|
||||
SawPolyTraitRef.hash(self.st);
|
||||
m.hash(self.st);
|
||||
|
@ -144,6 +144,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
});
|
||||
}
|
||||
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);
|
||||
}
|
||||
TyKind::ImplTrait(ref bounds) => {
|
||||
|
@ -244,6 +244,7 @@ match 5u32 {
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
E0226, // only a single explicit lifetime bound is permitted
|
||||
E0472, // asm! is unsupported on this target
|
||||
E0561, // patterns aren't allowed in function pointer types
|
||||
E0571, // `break` with a value in a non-`loop`-loop
|
||||
|
@ -453,24 +453,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
(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
|
||||
/// 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.
|
||||
@ -505,17 +487,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
fn ast_path_to_poly_trait_ref(&self,
|
||||
pub fn instantiate_poly_trait_ref(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
trait_def_id: DefId,
|
||||
ast_trait_ref: &hir::PolyTraitRef,
|
||||
self_ty: Ty<'tcx>,
|
||||
path_id: ast::NodeId,
|
||||
trait_segment: &hir::PathSegment,
|
||||
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'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
|
||||
// we need to shift the `rscope`. It'd be nice if we could
|
||||
// do away with this rscope stuff and work this knowledge
|
||||
@ -525,23 +507,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
self.create_substs_for_ast_trait_ref(shifted_rscope,
|
||||
span,
|
||||
trait_ref.path.span,
|
||||
trait_def_id,
|
||||
self_ty,
|
||||
trait_segment);
|
||||
trait_ref.path.segments.last().unwrap());
|
||||
let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));
|
||||
|
||||
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
|
||||
// specify type to assert that error was already reported in Err case:
|
||||
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,
|
||||
binding);
|
||||
predicate.ok() // ok to ignore Err() because ErrorReported (see above)
|
||||
}));
|
||||
|
||||
debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
|
||||
trait_segment, poly_projections, poly_trait_ref);
|
||||
debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
|
||||
trait_ref, poly_projections, poly_trait_ref);
|
||||
poly_trait_ref
|
||||
}
|
||||
|
||||
@ -754,32 +736,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
|
||||
}
|
||||
|
||||
fn trait_path_to_object_type(&self,
|
||||
rscope: &RegionScope,
|
||||
path_span: Span,
|
||||
trait_def_id: DefId,
|
||||
trait_path_ref_id: ast::NodeId,
|
||||
trait_segment: &hir::PathSegment,
|
||||
span: Span,
|
||||
partitioned_bounds: PartitionedBounds)
|
||||
-> Ty<'tcx> {
|
||||
fn conv_object_ty_poly_trait_ref(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
trait_bounds: &[hir::PolyTraitRef],
|
||||
lifetime: &hir::Lifetime)
|
||||
-> Ty<'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 dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
|
||||
let principal = self.ast_path_to_poly_trait_ref(rscope,
|
||||
path_span,
|
||||
trait_def_id,
|
||||
let principal = self.instantiate_poly_trait_ref(rscope,
|
||||
&trait_bounds[0],
|
||||
dummy_self,
|
||||
trait_path_ref_id,
|
||||
trait_segment,
|
||||
&mut projection_bounds);
|
||||
|
||||
let PartitionedBounds { trait_bounds,
|
||||
region_bounds } =
|
||||
partitioned_bounds;
|
||||
|
||||
let (auto_traits, trait_bounds) = split_auto_traits(tcx, trait_bounds);
|
||||
let (auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
|
||||
|
||||
if !trait_bounds.is_empty() {
|
||||
let b = &trait_bounds[0];
|
||||
@ -854,13 +833,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
v.sort_by(|a, b| a.cmp(tcx, b));
|
||||
let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter()));
|
||||
|
||||
let region_bound = self.compute_object_lifetime_bound(span,
|
||||
®ion_bounds,
|
||||
existential_predicates);
|
||||
|
||||
let region_bound = match region_bound {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
// Explicitly specified region bound. Use that.
|
||||
let region_bound = if !lifetime.is_elided() {
|
||||
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) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
@ -870,7 +848,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
ty::ReStatic
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
debug!("region_bound: {:?}", region_bound);
|
||||
@ -1330,8 +1308,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
tcx.mk_fn_ptr(bare_fn_ty)
|
||||
}
|
||||
hir::TyTraitObject(ref bounds) => {
|
||||
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
|
||||
hir::TyTraitObject(ref bounds, ref lifetime) => {
|
||||
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds, lifetime)
|
||||
}
|
||||
hir::TyImplTrait(ref bounds) => {
|
||||
use collect::{compute_bounds, SizedByDefault};
|
||||
@ -1537,33 +1515,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
/// 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
|
||||
@ -1571,27 +1522,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
/// we return `None`.
|
||||
fn compute_object_lifetime_bound(&self,
|
||||
span: Span,
|
||||
explicit_region_bounds: &[&hir::Lifetime],
|
||||
existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
|
||||
-> Option<&'tcx ty::Region> // if None, use the default
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
|
||||
existential_predicates={:?})",
|
||||
explicit_region_bounds,
|
||||
debug!("compute_opt_region_bound(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 Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
|
||||
return Some(tcx.mk_region(ty::ReStatic));
|
||||
@ -1627,18 +1565,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
/// remaining general trait bounds.
|
||||
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>)
|
||||
{
|
||||
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 {
|
||||
Def::Trait(trait_did) => {
|
||||
// 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>,
|
||||
(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,
|
||||
ty_param_defs: &[ty::TypeParameterDef]) {
|
||||
let accepted = ty_param_defs.len();
|
||||
|
@ -57,7 +57,7 @@ There are some shortcomings in this design:
|
||||
|
||||
*/
|
||||
|
||||
use astconv::{AstConv, Bounds, PartitionedBounds, partition_bounds};
|
||||
use astconv::{AstConv, Bounds};
|
||||
use lint;
|
||||
use constrained_type_params as ctp;
|
||||
use middle::lang_items::SizedTraitLangItem;
|
||||
@ -1961,10 +1961,19 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
||||
span: Span)
|
||||
-> Bounds<'tcx>
|
||||
{
|
||||
let PartitionedBounds {
|
||||
trait_bounds,
|
||||
region_bounds
|
||||
} = partition_bounds(&ast_bounds);
|
||||
let mut region_bounds = vec![];
|
||||
let mut trait_bounds = vec![];
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
|
||||
|
@ -4096,7 +4096,6 @@ register_diagnostics! {
|
||||
// E0222, // Error code E0045 (variadic function must have C calling
|
||||
// convention) duplicate
|
||||
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
|
||||
E0228, // explicit lifetime bound required
|
||||
E0231, // only named substitution parameters are allowed
|
||||
|
@ -1776,20 +1776,20 @@ impl Clean<Type> for hir::Ty {
|
||||
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
|
||||
}
|
||||
}
|
||||
TyTraitObject(ref bounds) => {
|
||||
let lhs_ty = bounds[0].clean(cx);
|
||||
match lhs_ty {
|
||||
TraitBound(poly_trait, ..) => {
|
||||
match poly_trait.trait_ {
|
||||
ResolvedPath { path, typarams: None, did, is_generic } => {
|
||||
ResolvedPath {
|
||||
path: path,
|
||||
typarams: Some(bounds[1..].clean(cx)),
|
||||
did: did,
|
||||
is_generic: is_generic,
|
||||
}
|
||||
}
|
||||
_ => Infer // shouldn't happen
|
||||
TyTraitObject(ref bounds, ref lifetime) => {
|
||||
match bounds[0].clean(cx).trait_ {
|
||||
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 {
|
||||
path: path,
|
||||
typarams: Some(bounds),
|
||||
did: did,
|
||||
is_generic: is_generic,
|
||||
}
|
||||
}
|
||||
_ => Infer // shouldn't happen
|
||||
|
@ -18,7 +18,7 @@ trait SomeTrait { }
|
||||
|
||||
// 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:
|
||||
a: Box<IsStatic>,
|
||||
b: Box<Is<'static>>,
|
||||
@ -28,7 +28,9 @@ struct Foo<'a,'b,'c> {
|
||||
f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599.
|
||||
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<
|
||||
|
Loading…
Reference in New Issue
Block a user