use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, PathResolution};
use session::Session;
+use util::nodemap::NodeMap;
use std::collections::BTreeMap;
use std::iter;
}
}
- fn lower_ty_param(&mut self, tp: &TyParam) -> hir::TyParam {
+ fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
let mut name = tp.ident.name;
// Don't expose `Self` (recovered "keyword used as ident" parse error).
name = Symbol::gensym("Self");
}
+ let mut bounds = self.lower_bounds(&tp.bounds);
+ if !add_bounds.is_empty() {
+ bounds = bounds.into_iter().chain(self.lower_bounds(add_bounds).into_iter()).collect();
+ }
+
hir::TyParam {
id: tp.id,
name: name,
- bounds: self.lower_bounds(&tp.bounds),
+ bounds: bounds,
default: tp.default.as_ref().map(|x| self.lower_ty(x)),
span: tp.span,
pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
}
}
- fn lower_ty_params(&mut self, tps: &P<[TyParam]>) -> hir::HirVec<hir::TyParam> {
- tps.iter().map(|tp| self.lower_ty_param(tp)).collect()
+ fn lower_ty_params(&mut self, tps: &P<[TyParam]>, add_bounds: &NodeMap<Vec<TyParamBound>>)
+ -> hir::HirVec<hir::TyParam> {
+ tps.iter().map(|tp| {
+ self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
+ }).collect()
}
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
}
fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
+ // Collect `?Trait` bounds in where clause and move them to parameter definitions.
+ let mut add_bounds = NodeMap();
+ for pred in &g.where_clause.predicates {
+ if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
+ 'next_bound: for bound in &bound_pred.bounds {
+ if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
+ let report_error = |this: &mut Self| {
+ this.diagnostic().span_err(bound_pred.bounded_ty.span,
+ "`?Trait` bounds are only permitted at the \
+ point where a type parameter is declared");
+ };
+ // Check if the where clause type is a plain type parameter.
+ match bound_pred.bounded_ty.node {
+ TyKind::Path(None, ref path)
+ if !path.global && path.segments.len() == 1 &&
+ bound_pred.bound_lifetimes.is_empty() => {
+ if let Some(Def::TyParam(def_id)) =
+ self.resolver.get_resolution(bound_pred.bounded_ty.id)
+ .map(|d| d.base_def) {
+ if let Some(node_id) =
+ self.resolver.definitions().as_local_node_id(def_id) {
+ for ty_param in &g.ty_params {
+ if node_id == ty_param.id {
+ add_bounds.entry(ty_param.id).or_insert(Vec::new())
+ .push(bound.clone());
+ continue 'next_bound;
+ }
+ }
+ }
+ }
+ report_error(self)
+ }
+ _ => report_error(self)
+ }
+ }
+ }
+ }
+ }
+
hir::Generics {
- ty_params: self.lower_ty_params(&g.ty_params),
+ ty_params: self.lower_ty_params(&g.ty_params, &add_bounds),
lifetimes: self.lower_lifetime_defs(&g.lifetimes),
where_clause: self.lower_where_clause(&g.where_clause),
span: g.span,
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
bounded_ty: self.lower_ty(bounded_ty),
- bounds: bounds.iter().map(|x| self.lower_ty_param_bound(x)).collect(),
+ bounds: bounds.iter().filter_map(|bound| match *bound {
+ // Ignore `?Trait` bounds, they were copied into type parameters already.
+ TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
+ _ => Some(self.lower_ty_param_bound(bound))
+ }).collect(),
span: span,
})
}
}
}
- fn lower_bounds(&mut self, bounds: &TyParamBounds) -> hir::TyParamBounds {
+ fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
}
_ => {}
}
}
+
+ fn no_questions_in_bounds(&self, bounds: &TyParamBounds, where_: &str, is_trait: bool) {
+ for bound in bounds {
+ if let TraitTyParamBound(ref poly, TraitBoundModifier::Maybe) = *bound {
+ let mut err = self.err_handler().struct_span_err(poly.span,
+ &format!("`?Trait` is not permitted in {}", where_));
+ if is_trait {
+ err.note(&format!("traits are `?{}` by default", poly.trait_ref.path));
+ }
+ err.emit();
+ }
+ }
+ }
}
impl<'a> Visitor for AstValidator<'a> {
err.emit();
});
}
+ TyKind::ObjectSum(_, ref bounds) |
+ TyKind::PolyTraitRef(ref bounds) => {
+ self.no_questions_in_bounds(bounds, "trait object types", false);
+ }
_ => {}
}
}
}
}
- ItemKind::Trait(.., ref trait_items) => {
+ ItemKind::Trait(.., ref bounds, ref trait_items) => {
+ self.no_questions_in_bounds(bounds, "supertraits", true);
for trait_item in trait_items {
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
self.check_trait_fn_not_const(sig.constness);
Expr,
}
-/// How to parse a bound, whether to allow bound modifiers such as `?`.
-#[derive(Copy, Clone, PartialEq)]
-pub enum BoundParsingMode {
- Bare,
- Modified,
-}
-
#[derive(Clone, Copy, PartialEq)]
pub enum SemiColonMode {
Break,
trait_ref: trait_ref,
span: mk_sp(lo, hi)};
let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
- self.parse_ty_param_bounds(BoundParsingMode::Bare)?
+ self.parse_ty_param_bounds()?
} else {
P::new()
};
The `impl` has already been consumed.
*/
- let bounds = self.parse_ty_param_bounds(BoundParsingMode::Modified)?;
+ let bounds = self.parse_ty_param_bounds()?;
if !bounds.iter().any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
self.span_err(self.prev_span, "at least one trait must be specified");
return Ok(lhs);
}
- let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?;
+ let bounds = self.parse_ty_param_bounds()?;
// In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required.
// Parses a sequence of bounds if a `:` is found,
// otherwise returns empty list.
- fn parse_colon_then_ty_param_bounds(&mut self,
- mode: BoundParsingMode)
- -> PResult<'a, TyParamBounds>
+ fn parse_colon_then_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds>
{
if !self.eat(&token::Colon) {
Ok(P::new())
} else {
- self.parse_ty_param_bounds(mode)
+ self.parse_ty_param_bounds()
}
}
// where boundseq = ( polybound + boundseq ) | polybound
// and polybound = ( 'for' '<' 'region '>' )? bound
// and bound = 'region | trait_ref
- fn parse_ty_param_bounds(&mut self,
- mode: BoundParsingMode)
- -> PResult<'a, TyParamBounds>
+ fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds>
{
let mut result = vec![];
loop {
token::ModSep | token::Ident(..) => {
let poly_trait_ref = self.parse_poly_trait_ref()?;
let modifier = if ate_question {
- if mode == BoundParsingMode::Modified {
- TraitBoundModifier::Maybe
- } else {
- self.span_err(question_span,
- "unexpected `?`");
- TraitBoundModifier::None
- }
+ TraitBoundModifier::Maybe
} else {
TraitBoundModifier::None
};
let span = self.span;
let ident = self.parse_ident()?;
- let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified)?;
+ let bounds = self.parse_colon_then_ty_param_bounds()?;
let default = if self.check(&token::Eq) {
self.bump();
let bounded_ty = self.parse_ty()?;
if self.eat(&token::Colon) {
- let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?;
+ let bounds = self.parse_ty_param_bounds()?;
let hi = self.prev_span.hi;
let span = mk_sp(lo, hi);
let mut tps = self.parse_generics()?;
// Parse supertrait bounds.
- let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare)?;
+ let bounds = self.parse_colon_then_ty_param_bounds()?;
tps.where_clause = self.parse_where_clause()?;
--- /dev/null
+// Copyright 2016 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+struct S<T>(*const T) where T: ?Sized;
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+ let u = vec![1, 2, 3];
+ let _s: S<[u8]> = S(&u[..]);
+}
--- /dev/null
+// Copyright 2016 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S1<T>(T) where (T): ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S2<T>(T) where u8: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S3<T>(T) where &'static T: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+trait Trait<'a> {}
+
+struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+//~^ ERROR type parameter has more than one relaxed default bound
+//~| WARN default bound relaxed for a type parameter
+
+impl<T> S1<T> {
+ fn f() where T: ?Sized {}
+ //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+}
+
+fn main() {
+ let u = vec![1, 2, 3];
+ let _s: S5<[u8]> = S5(&u[..]); // OK
+}
--- /dev/null
+// Copyright 2016 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits
+ //~^ NOTE traits are `?Sized` by default
+
+type A1 = Tr + ?Sized; //~ ERROR `?Trait` is not permitted in trait object types
+type A2 = for<'a> Tr + ?Sized; //~ ERROR `?Trait` is not permitted in trait object types
+
+fn main() {}