use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::{GenericParamDef, GenericParamDefKind};
use rustc::ty::wf::object_region_bounds;
+use rustc_data_structures::sync::Lrc;
use rustc_target::spec::abi;
use std::collections::BTreeSet;
use std::slice;
use syntax::ast;
use syntax::ptr::P;
use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax_pos::{Span, MultiSpan};
+use syntax_pos::{DUMMY_SP, Span, MultiSpan};
pub trait AstConv<'gcx, 'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
/// Returns the set of bounds in scope for the type parameter with
/// the given id.
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
- -> ty::GenericPredicates<'tcx>;
+ -> Lrc<ty::GenericPredicates<'tcx>>;
/// What lifetime should we use when a lifetime is omitted (and not elided)?
fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
(required, "")
};
- let mut span = span;
- let label = if required == permitted && provided > permitted {
- let diff = provided - permitted;
- if diff == 1 {
- // In the case when the user has provided too many arguments,
- // we want to point to the first unexpected argument.
- let first_superfluous_arg: &GenericArg = &args.args[offset + permitted];
- span = first_superfluous_arg.span();
- }
- format!(
- "{}unexpected {} argument{}",
- if diff != 1 { format!("{} ", diff) } else { String::new() },
- kind,
- if diff != 1 { "s" } else { "" },
+ let (spans, label) = if required == permitted && provided > permitted {
+ // In the case when the user has provided too many arguments,
+ // we want to point to the unexpected arguments.
+ (
+ args.args[offset+permitted .. offset+provided]
+ .iter()
+ .map(|arg| arg.span())
+ .collect(),
+ format!(
+ "unexpected {} argument",
+ kind,
+ ),
)
} else {
- format!(
+ (vec![span], format!(
"expected {}{} {} argument{}",
quantifier,
bound,
kind,
if bound != 1 { "s" } else { "" },
- )
+ ))
};
- tcx.sess.struct_span_err_with_code(
- span,
+ let mut err = tcx.sess.struct_span_err_with_code(
+ spans.clone(),
&format!(
"wrong number of {} arguments: expected {}{}, found {}",
kind,
provided,
),
DiagnosticId::Error("E0107".into())
- ).span_label(span, label).emit();
+ );
+ for span in spans {
+ err.span_label(span, label.as_str());
+ }
+ err.emit();
provided > required // `suppress_error`
};
}
// We manually build up the substitution, rather than using convenience
- // methods in subst.rs so that we can iterate over the arguments and
+ // methods in `subst.rs` so that we can iterate over the arguments and
// parameters in lock-step linearly, rather than trying to match each pair.
let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count);
}
}
- // (Unless it's been handled in `parent_substs`) `Self` is handled first.
+ // `Self` is handled first, unless it's been handled in `parent_substs`.
if has_self {
if let Some(¶m) = params.peek() {
if param.index == 0 {
trait_ref.path.segments.last().unwrap())
}
- /// Get the DefId of the given trait ref. It _must_ actually be a trait.
+ /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
let path = &trait_ref.path;
match path.def {
}
}
- /// The given `trait_ref` must actually be trait.
+ /// The given trait ref must actually be a trait.
pub(super) fn instantiate_poly_trait_ref_inner(&self,
trait_ref: &hir::TraitRef,
self_ty: Ty<'tcx>,
let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate(
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
- // ok to ignore Err because ErrorReported (see above)
+ // okay to ignore Err because of ErrorReported (see above)
Some((predicate.ok()?, binding.span))
}));
let tcx = self.tcx();
if !speculative {
- // Given something like `U : SomeTrait<T=X>`, we want to produce a
+ // Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
// subtle in the event that `T` is defined in a supertrait of
// `SomeTrait`, because in that case we need to upcast.
// That is, consider this case:
//
// ```
- // trait SubTrait : SuperTrait<int> { }
+ // trait SubTrait: SuperTrait<int> { }
// trait SuperTrait<A> { type T; }
//
// ... B : SubTrait<T=foo> ...
if !speculative {
dup_bindings.entry(assoc_ty.def_id)
.and_modify(|prev_span| {
- let mut err = self.tcx().struct_span_lint_node(
- ::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
- ref_id,
- binding.span,
- &format!("associated type binding `{}` specified more than once",
- binding.item_name)
- );
- err.span_label(binding.span, "used more than once");
- err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
- err.emit();
+ struct_span_err!(self.tcx().sess, binding.span, E0719,
+ "the value of the associated type `{}` (from the trait `{}`) \
+ is already specified",
+ binding.item_name,
+ tcx.item_path_str(assoc_ty.container.id()))
+ .span_label(binding.span, "re-bound here")
+ .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
+ .emit();
})
.or_insert(binding.span);
}
return tcx.types.err;
}
- let mut projection_bounds = vec![];
+ let mut projection_bounds = Vec::new();
let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
dummy_self,
.emit();
}
- // Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above.
- let existential_principal = principal.map_bound(|trait_ref| {
- self.trait_ref_to_existential(trait_ref)
- });
- let existential_projections = projection_bounds.iter().map(|(bound, _)| {
- bound.map_bound(|b| {
- let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
- ty::ExistentialProjection {
- ty: b.ty,
- item_def_id: b.projection_ty.item_def_id,
- substs: trait_ref.substs,
- }
- })
- });
-
// Check that there are no gross object safety violations;
- // most importantly, that the supertraits don't contain Self,
+ // most importantly, that the supertraits don't contain `Self`,
// to avoid ICEs.
let object_safety_violations =
tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
return tcx.types.err;
}
- // Use a BTreeSet to keep output in a more consistent order.
+ // Use a `BTreeSet` to keep output in a more consistent order.
let mut associated_types = BTreeSet::default();
- for tr in traits::supertraits(tcx, principal) {
- associated_types.extend(tcx.associated_items(tr.def_id())
- .filter(|item| item.kind == ty::AssociatedKind::Type)
- .map(|item| item.def_id));
+ for tr in traits::elaborate_trait_ref(tcx, principal) {
+ match tr {
+ ty::Predicate::Trait(pred) => {
+ associated_types.extend(tcx.associated_items(pred.def_id())
+ .filter(|item| item.kind == ty::AssociatedKind::Type)
+ .map(|item| item.def_id));
+ }
+ ty::Predicate::Projection(pred) => {
+ // Include projections defined on supertraits.
+ projection_bounds.push((pred, DUMMY_SP))
+ }
+ _ => ()
+ }
}
for (projection_bound, _) in &projection_bounds {
for item_def_id in associated_types {
let assoc_item = tcx.associated_item(item_def_id);
let trait_def_id = assoc_item.container.id();
- struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` \
- (from the trait `{}`) must be specified",
- assoc_item.ident,
- tcx.item_path_str(trait_def_id))
- .span_label(span, format!("missing associated type `{}` value",
- assoc_item.ident))
- .emit();
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0191,
+ "the value of the associated type `{}` (from the trait `{}`) must be specified",
+ assoc_item.ident,
+ tcx.item_path_str(trait_def_id),
+ );
+ err.span_label(span, format!("missing associated type `{}` value", assoc_item.ident));
+ err.emit();
}
+ // Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
+ let existential_principal = principal.map_bound(|trait_ref| {
+ self.trait_ref_to_existential(trait_ref)
+ });
+ let existential_projections = projection_bounds.iter().map(|(bound, _)| {
+ bound.map_bound(|b| {
+ let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
+ ty::ExistentialProjection {
+ ty: b.ty,
+ item_def_id: b.projection_ty.item_def_id,
+ substs: trait_ref.substs,
+ }
+ })
+ });
+
// Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
auto_traits.sort();
auto_traits.dedup();
- // skip_binder is okay, because the predicates are re-bound.
+ // Calling `skip_binder` is okay, because the predicates are re-bound.
let mut v =
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
.chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
{
let tcx = self.tcx();
- let bounds = self.get_type_parameter_bounds(span, ty_param_def_id)
- .predicates.into_iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
+ let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates;
+ let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
// Check that there is exactly one way to find an associated type with the
// correct name.
span)
}
-
- // Checks that bounds contains exactly one element and reports appropriate
+ // Checks that `bounds` contains exactly one element and reports appropriate
// errors otherwise.
fn one_bound_for_assoc_type<I>(&self,
mut bounds: I,
}
// Create a type from a path to an associated type.
- // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
- // and item_segment is the path segment for D. We return a type and a def for
+ // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
+ // and item_segment is the path segment for `D`. We return a type and a def for
// the whole path.
- // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
- // parameter or Self.
+ // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
+ // parameter or `Self`.
pub fn associated_path_def_to_ty(&self,
ref_id: ast::NodeId,
span: Span,
// item is declared.
let bound = match (&ty.sty, ty_path_def) {
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
- // `Self` in an impl of a trait - we have a concrete self type and a
+ // `Self` in an impl of a trait - we have a concrete `self` type and a
// trait reference.
let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
Some(trait_ref) => trait_ref,
let span = path.span;
match path.def {
Def::Existential(did) => {
- // check for desugared impl trait
+ // Check for desugared impl trait.
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
let item_segment = path.segments.split_last().unwrap();
self.prohibit_generics(item_segment.1);
tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
}
Def::SelfTy(_, Some(def_id)) => {
- // Self in impl (we know the concrete type).
+ // `Self` in impl (we know the concrete type)
assert_eq!(opt_self_ty, None);
self.prohibit_generics(&path.segments);
tcx.at(span).type_of(def_id)
}
Def::SelfTy(Some(_), None) => {
- // Self in trait.
+ // `Self` in trait
assert_eq!(opt_self_ty, None);
self.prohibit_generics(&path.segments);
tcx.mk_self_type()