]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/astconv.rs
Point at every unexpected lifetime and type argument in E0107
[rust.git] / src / librustc_typeck / astconv.rs
index 18f8473b5b56d7d88fb600878aaa16ff8fbbe0b3..277f7d345462e0e7fdbed286ea609f7cee6e6b0e 100644 (file)
@@ -24,6 +24,7 @@
 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;
@@ -37,7 +38,7 @@
 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>;
@@ -45,7 +46,7 @@ pub trait AstConv<'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>)
@@ -337,33 +338,31 @@ fn check_generic_arg_count(
                 (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,
@@ -372,7 +371,11 @@ fn check_generic_arg_count(
                     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`
         };
@@ -451,7 +454,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
         }
 
         // 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);
 
@@ -469,7 +472,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
                 }
             }
 
-            // (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(&param) = params.peek() {
                     if param.index == 0 {
@@ -698,7 +701,7 @@ pub fn instantiate_mono_trait_ref(&self,
                                         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 {
@@ -711,7 +714,7 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
         }
     }
 
-    /// 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>,
@@ -738,7 +741,7 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
             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))
         }));
 
@@ -831,7 +834,7 @@ fn ast_type_binding_to_poly_projection_predicate(
         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.
@@ -839,7 +842,7 @@ fn ast_type_binding_to_poly_projection_predicate(
             // That is, consider this case:
             //
             // ```
-            // trait SubTrait : SuperTrait<int> { }
+            // trait SubTrait: SuperTrait<int> { }
             // trait SuperTrait<A> { type T; }
             //
             // ... B : SubTrait<T=foo> ...
@@ -908,16 +911,14 @@ fn ast_type_binding_to_poly_projection_predicate(
         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);
         }
@@ -969,7 +970,7 @@ fn conv_object_ty_poly_trait_ref(&self,
             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,
@@ -994,23 +995,8 @@ fn conv_object_ty_poly_trait_ref(&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());
@@ -1021,13 +1007,22 @@ fn conv_object_ty_poly_trait_ref(&self,
             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 {
@@ -1037,20 +1032,38 @@ fn conv_object_ty_poly_trait_ref(&self,
         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))
@@ -1112,8 +1125,8 @@ fn find_bound_for_assoc_item(&self,
     {
         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.
@@ -1128,8 +1141,7 @@ fn find_bound_for_assoc_item(&self,
                                       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,
@@ -1186,11 +1198,11 @@ fn one_bound_for_assoc_type<I>(&self,
     }
 
     // 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,
@@ -1210,7 +1222,7 @@ pub fn associated_path_def_to_ty(&self,
         // 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,
@@ -1361,7 +1373,7 @@ pub fn def_to_ty(&self,
         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);
@@ -1398,7 +1410,7 @@ pub fn def_to_ty(&self,
                 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);
@@ -1406,7 +1418,7 @@ pub fn def_to_ty(&self,
                 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()