]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #53504 - ekse:suggestions-applicability-2, r=estebank
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 22 Aug 2018 15:45:34 +0000 (17:45 +0200)
committerGitHub <noreply@github.com>
Wed, 22 Aug 2018 15:45:34 +0000 (17:45 +0200)
Set applicability for more suggestions.

Converts a couple more calls to `span_suggestion_with_applicability`  (#50723). To be on the safe side, I marked suggestions that depend on the intent of the user or that are potentially lossy conversions as MaybeIncorrect.

r? @estebank

1  2 
src/librustc_passes/ast_validation.rs
src/librustc_resolve/macros.rs
src/librustc_typeck/check/mod.rs
src/libsyntax_ext/format.rs

index 11d1d85c97d394a2d7bd44cd7aa933d1f02de0ba,ca7dcbcc307b858667db52bc4e3bf6b1d78ef4f3..bca119660aa2a4e93a9dd14768fa1d64b0dd2032
@@@ -25,6 -25,7 +25,7 @@@ use syntax::symbol::keywords
  use syntax::visit::{self, Visitor};
  use syntax_pos::Span;
  use errors;
+ use errors::Applicability;
  
  struct AstValidator<'a> {
      session: &'a Session,
@@@ -185,11 -186,12 +186,12 @@@ impl<'a> Visitor<'a> for AstValidator<'
                  );
                  match val.node {
                      ExprKind::Lit(ref v) if v.node.is_numeric() => {
-                         err.span_suggestion(
+                         err.span_suggestion_with_applicability(
                              place.span.between(val.span),
                              "if you meant to write a comparison against a negative value, add a \
                               space in between `<` and `-`",
                              "< -".to_string(),
+                             Applicability::MaybeIncorrect
                          );
                      }
                      _ => {}
@@@ -539,9 -541,10 +541,9 @@@ impl<'a> Visitor<'a> for NestedImplTrai
      fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
          match *generic_args {
              GenericArgs::AngleBracketed(ref data) => {
 -                data.args.iter().for_each(|arg| match arg {
 -                    GenericArg::Type(ty) => self.visit_ty(ty),
 -                    _ => {}
 -                });
 +                for arg in &data.args {
 +                    self.visit_generic_arg(arg)
 +                }
                  for type_binding in &data.bindings {
                      // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
                      // are allowed to contain nested `impl Trait`.
index 1161d57417b1890865c4590a6da8f698c96bea7e,0a33aae076be17dde084bb717213f1a18acfb5b7..fcdb8fb1465eb2ab0f01f861e1919d685ad26e79
@@@ -38,14 -38,12 +38,15 @@@ use syntax::symbol::{Symbol, keywords}
  use syntax::tokenstream::{TokenStream, TokenTree, Delimited};
  use syntax::util::lev_distance::find_best_match_for_name;
  use syntax_pos::{Span, DUMMY_SP};
+ use errors::Applicability;
  
  use std::cell::Cell;
  use std::mem;
  use rustc_data_structures::sync::Lrc;
  
 +crate struct FromPrelude(bool);
 +crate struct FromExpansion(bool);
 +
  #[derive(Clone)]
  pub struct InvocationData<'a> {
      pub module: Cell<Module<'a>>,
@@@ -83,12 -81,6 +84,12 @@@ pub struct LegacyBinding<'a> 
      pub span: Span,
  }
  
 +impl<'a> LegacyBinding<'a> {
 +    fn def(&self) -> Def {
 +        Def::Macro(self.def_id, MacroKind::Bang)
 +    }
 +}
 +
  pub struct ProcMacError {
      crate_name: Symbol,
      name: Symbol,
      warn_msg: &'static str,
  }
  
 -#[derive(Copy, Clone)]
 -pub enum MacroBinding<'a> {
 -    Legacy(&'a LegacyBinding<'a>),
 -    Global(&'a NameBinding<'a>),
 -    Modern(&'a NameBinding<'a>),
 -}
 -
 -impl<'a> MacroBinding<'a> {
 -    pub fn span(self) -> Span {
 -        match self {
 -            MacroBinding::Legacy(binding) => binding.span,
 -            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span,
 -        }
 -    }
 -
 -    pub fn binding(self) -> &'a NameBinding<'a> {
 -        match self {
 -            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding,
 -            MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"),
 -        }
 -    }
 -
 -    pub fn def_ignoring_ambiguity(self) -> Def {
 -        match self {
 -            MacroBinding::Legacy(binding) => Def::Macro(binding.def_id, MacroKind::Bang),
 -            MacroBinding::Global(binding) | MacroBinding::Modern(binding) =>
 -                binding.def_ignoring_ambiguity(),
 -        }
 -    }
 -}
 -
  impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
      fn next_node_id(&mut self) -> ast::NodeId {
          self.session.next_node_id()
          None
      }
  
 -    fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
 -                     -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
 -        let def = match invoc.kind {
 -            InvocationKind::Attr { attr: None, .. } => return Ok(None),
 -            _ => self.resolve_invoc_to_def(invoc, scope, force)?,
 +    fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
 +                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
 +        let (path, kind, derives_in_scope) = match invoc.kind {
 +            InvocationKind::Attr { attr: None, .. } =>
 +                return Ok(None),
 +            InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } =>
 +                (&attr.path, MacroKind::Attr, &traits[..]),
 +            InvocationKind::Bang { ref mac, .. } =>
 +                (&mac.node.path, MacroKind::Bang, &[][..]),
 +            InvocationKind::Derive { ref path, .. } =>
 +                (path, MacroKind::Derive, &[][..]),
          };
 -        if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
 -            self.report_proc_macro_stub(invoc.span());
 -            return Err(Determinacy::Determined);
 -        } else if let Def::NonMacroAttr(attr_kind) = def {
 -            // Note that not only attributes, but anything in macro namespace can result in a
 -            // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report the error
 -            // below for these cases.
 -            let is_attr_invoc =
 -                if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
 -            let path = invoc.path().expect("no path for non-macro attr");
 -            match attr_kind {
 -                NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
 -                NonMacroAttrKind::Custom if is_attr_invoc => {
 -                    let features = self.session.features_untracked();
 -                    if attr_kind == NonMacroAttrKind::Tool &&
 -                       !features.tool_attributes {
 -                        feature_err(&self.session.parse_sess, "tool_attributes",
 -                                    invoc.span(), GateIssue::Language,
 -                                    "tool attributes are unstable").emit();
 -                    }
 -                    if attr_kind == NonMacroAttrKind::Custom {
 -                        assert!(path.segments.len() == 1);
 -                        let name = path.segments[0].ident.name.as_str();
 -                        if name.starts_with("rustc_") {
 -                            if !features.rustc_attrs {
 -                                let msg = "unless otherwise specified, attributes with the prefix \
 -                                        `rustc_` are reserved for internal compiler diagnostics";
 -                                feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(),
 -                                            GateIssue::Language, &msg).emit();
 -                            }
 -                        } else if name.starts_with("derive_") {
 -                            if !features.custom_derive {
 -                                feature_err(&self.session.parse_sess, "custom_derive", invoc.span(),
 -                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
 -                            }
 -                        } else if !features.custom_attribute {
 -                            let msg = format!("The attribute `{}` is currently unknown to the \
 -                                               compiler and may have meaning added to it in the \
 -                                               future", path);
 -                            feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
 -                                        GateIssue::Language, &msg).emit();
 -                        }
 -                    }
  
 -                    return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
 -                        mark_used: attr_kind == NonMacroAttrKind::Tool,
 -                    })));
 -                }
 -                _ => {
 -                    self.report_non_macro_attr(path.span, def);
 -                    return Err(Determinacy::Determined);
 -                }
 -            }
 +        let (def, ext) = self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?;
 +
 +        if let Def::Macro(def_id, _) = def {
 +            self.macro_defs.insert(invoc.expansion_data.mark, def_id);
 +            let normal_module_def_id =
 +                self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
 +            self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
 +                                                            normal_module_def_id);
 +            invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
 +            invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE);
          }
 -        let def_id = def.def_id();
 -
 -        self.macro_defs.insert(invoc.expansion_data.mark, def_id);
 -        let normal_module_def_id =
 -            self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
 -        self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
 -                                                        normal_module_def_id);
 -
 -        self.unused_macros.remove(&def_id);
 -        let ext = self.get_macro(def);
 -        invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
 -        invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE);
 +
          Ok(Some(ext))
      }
  
 -    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
 -                     -> Result<Lrc<SyntaxExtension>, Determinacy> {
 -        self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| {
 -            if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
 -                self.report_proc_macro_stub(path.span);
 -                return Err(Determinacy::Determined);
 -            } else if let Def::NonMacroAttr(..) = def {
 -                self.report_non_macro_attr(path.span, def);
 -                return Err(Determinacy::Determined);
 -            }
 -            self.unused_macros.remove(&def.def_id());
 -            Ok(self.get_macro(def))
 -        })
 +    fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
 +                          derives_in_scope: &[ast::Path], force: bool)
 +                          -> Result<Lrc<SyntaxExtension>, Determinacy> {
 +        Ok(self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?.1)
      }
  
      fn check_unused_macros(&self) {
  }
  
  impl<'a, 'cl> Resolver<'a, 'cl> {
 -    fn report_proc_macro_stub(&self, span: Span) {
 -        self.session.span_err(span,
 -                              "can't use a procedural macro from the same crate that defines it");
 -    }
 +    fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
 +                            derives_in_scope: &[ast::Path], force: bool)
 +                            -> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
 +        let def = self.resolve_macro_to_def_inner(path, kind, scope, derives_in_scope, force);
  
 -    fn report_non_macro_attr(&self, span: Span, def: Def) {
 -        self.session.span_err(span, &format!("expected a macro, found {}", def.kind_name()));
 -    }
 -
 -    fn resolve_invoc_to_def(&mut self, invoc: &Invocation, scope: Mark, force: bool)
 -                            -> Result<Def, Determinacy> {
 -        let (attr, traits) = match invoc.kind {
 -            InvocationKind::Attr { ref attr, ref traits, .. } => (attr, traits),
 -            InvocationKind::Bang { ref mac, .. } => {
 -                return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force);
 -            }
 -            InvocationKind::Derive { ref path, .. } => {
 -                return self.resolve_macro_to_def(scope, path, MacroKind::Derive, force);
 +        // Report errors and enforce feature gates for the resolved macro.
 +        if def != Err(Determinacy::Undetermined) {
 +            // Do not report duplicated errors on every undetermined resolution.
 +            for segment in &path.segments {
 +                if let Some(args) = &segment.args {
 +                    self.session.span_err(args.span(), "generic arguments in macro path");
 +                }
              }
 -        };
 -
 -        let path = attr.as_ref().unwrap().path.clone();
 -        let def = self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force);
 -        if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = def {} else {
 -            return def;
          }
  
 -        // At this point we've found that the `attr` is determinately unresolved and thus can be
 -        // interpreted as a custom attribute. Normally custom attributes are feature gated, but
 -        // it may be a custom attribute whitelisted by a derive macro and they do not require
 -        // a feature gate.
 -        //
 -        // So here we look through all of the derive annotations in scope and try to resolve them.
 -        // If they themselves successfully resolve *and* one of the resolved derive macros
 -        // whitelists this attribute's name, then this is a registered attribute and we can convert
 -        // it from a "generic custom attrite" into a "known derive helper attribute".
 -        enum ConvertToDeriveHelper { Yes, No, DontKnow }
 -        let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
 -        let attr_name = path.segments[0].ident.name;
 -        for path in traits {
 -            match self.resolve_macro(scope, path, MacroKind::Derive, force) {
 -                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
 -                    if inert_attrs.contains(&attr_name) {
 -                        convert_to_derive_helper = ConvertToDeriveHelper::Yes;
 -                        break
 -                    }
 -                },
 -                Err(Determinacy::Undetermined) =>
 -                    convert_to_derive_helper = ConvertToDeriveHelper::DontKnow,
 -                Err(Determinacy::Determined) => {}
 -            }
 -        }
 +        let def = def?;
  
 -        match convert_to_derive_helper {
 -            ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)),
 -            ConvertToDeriveHelper::No => def,
 -            ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)),
 +        if path.segments.len() > 1 {
 +            if kind != MacroKind::Bang {
 +                if def != Def::NonMacroAttr(NonMacroAttrKind::Tool) &&
 +                   !self.session.features_untracked().proc_macro_path_invoc {
 +                    let msg = format!("non-ident {} paths are unstable", kind.descr());
 +                    emit_feature_err(&self.session.parse_sess, "proc_macro_path_invoc",
 +                                     path.span, GateIssue::Language, &msg);
 +                }
 +            }
          }
 -    }
  
 -    fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
 -                            -> Result<Def, Determinacy> {
 -        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
 -        if def != Err(Determinacy::Undetermined) {
 -            // Do not report duplicated errors on every undetermined resolution.
 -            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
 -                self.session.span_err(segment.args.as_ref().unwrap().span(),
 -                                      "generic arguments in macro path");
 -            });
 -        }
 -        if kind != MacroKind::Bang && path.segments.len() > 1 &&
 -           def != Ok(Def::NonMacroAttr(NonMacroAttrKind::Tool)) {
 -            if !self.session.features_untracked().proc_macro_path_invoc {
 -                emit_feature_err(
 -                    &self.session.parse_sess,
 -                    "proc_macro_path_invoc",
 -                    path.span,
 -                    GateIssue::Language,
 -                    "paths of length greater than one in macro invocations are \
 -                     currently unstable",
 -                );
 +        match def {
 +            Def::Macro(def_id, macro_kind) => {
 +                self.unused_macros.remove(&def_id);
 +                if macro_kind == MacroKind::ProcMacroStub {
 +                    let msg = "can't use a procedural macro from the same crate that defines it";
 +                    self.session.span_err(path.span, msg);
 +                    return Err(Determinacy::Determined);
 +                }
 +            }
 +            Def::NonMacroAttr(attr_kind) => {
 +                if kind == MacroKind::Attr {
 +                    let features = self.session.features_untracked();
 +                    if attr_kind == NonMacroAttrKind::Tool && !features.tool_attributes {
 +                        feature_err(&self.session.parse_sess, "tool_attributes", path.span,
 +                                    GateIssue::Language, "tool attributes are unstable").emit();
 +                    }
 +                    if attr_kind == NonMacroAttrKind::Custom {
 +                        assert!(path.segments.len() == 1);
 +                        let name = path.segments[0].ident.name.as_str();
 +                        if name.starts_with("rustc_") {
 +                            if !features.rustc_attrs {
 +                                let msg = "unless otherwise specified, attributes with the prefix \
 +                                           `rustc_` are reserved for internal compiler diagnostics";
 +                                feature_err(&self.session.parse_sess, "rustc_attrs", path.span,
 +                                            GateIssue::Language, &msg).emit();
 +                            }
 +                        } else if name.starts_with("derive_") {
 +                            if !features.custom_derive {
 +                                feature_err(&self.session.parse_sess, "custom_derive", path.span,
 +                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
 +                            }
 +                        } else if !features.custom_attribute {
 +                            let msg = format!("The attribute `{}` is currently unknown to the \
 +                                               compiler and may have meaning added to it in the \
 +                                               future", path);
 +                            feature_err(&self.session.parse_sess, "custom_attribute", path.span,
 +                                        GateIssue::Language, &msg).emit();
 +                        }
 +                    }
 +                } else {
 +                    // Not only attributes, but anything in macro namespace can result in
 +                    // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report
 +                    // an error for those cases.
 +                    let msg = format!("expected a macro, found {}", def.kind_name());
 +                    self.session.span_err(path.span, &msg);
 +                    return Err(Determinacy::Determined);
 +                }
              }
 +            _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
          }
 -        def
 +
 +        Ok((def, self.get_macro(def)))
      }
  
 -    pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
 -                                  kind: MacroKind, force: bool)
 -                                  -> Result<Def, Determinacy> {
 +    pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
 +                                      derives_in_scope: &[ast::Path], force: bool)
 +                                      -> Result<Def, Determinacy> {
          let ast::Path { ref segments, span } = *path;
          let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
          let invocation = self.invocations[&scope];
          }
  
          let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
 -        let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
 -            Ok(Def::Macro(binding.def_id, MacroKind::Bang))
 +        let result = if let Some((legacy_binding, _)) = legacy_resolution {
 +            Ok(legacy_binding.def())
          } else {
              match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, force,
                                                            kind == MacroKind::Attr, span) {
 -                Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
 +                Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
                  Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
                  Err(Determinacy::Determined) => {
                      self.found_unresolved_macro = true;
          self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
              .push((scope, path[0], kind, result.ok()));
  
 -        result
 +        if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else {
 +            return result;
 +        }
 +
 +        // At this point we've found that the `attr` is determinately unresolved and thus can be
 +        // interpreted as a custom attribute. Normally custom attributes are feature gated, but
 +        // it may be a custom attribute whitelisted by a derive macro and they do not require
 +        // a feature gate.
 +        //
 +        // So here we look through all of the derive annotations in scope and try to resolve them.
 +        // If they themselves successfully resolve *and* one of the resolved derive macros
 +        // whitelists this attribute's name, then this is a registered attribute and we can convert
 +        // it from a "generic custom attrite" into a "known derive helper attribute".
 +        assert!(kind == MacroKind::Attr);
 +        enum ConvertToDeriveHelper { Yes, No, DontKnow }
 +        let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
 +        for derive in derives_in_scope {
 +            match self.resolve_macro_path(derive, MacroKind::Derive, scope, &[], force) {
 +                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
 +                    if inert_attrs.contains(&path[0].name) {
 +                        convert_to_derive_helper = ConvertToDeriveHelper::Yes;
 +                        break
 +                    }
 +                },
 +                Err(Determinacy::Undetermined) =>
 +                    convert_to_derive_helper = ConvertToDeriveHelper::DontKnow,
 +                Err(Determinacy::Determined) => {}
 +            }
 +        }
 +
 +        match convert_to_derive_helper {
 +            ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)),
 +            ConvertToDeriveHelper::No => result,
 +            ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)),
 +        }
      }
  
      // Resolve the initial segment of a non-global macro path
      // (e.g. `foo` in `foo::bar!(); or `foo!();`).
      // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
      // expansion and import resolution (perhaps they can be merged in the future).
 -    pub fn resolve_lexical_macro_path_segment(&mut self,
 -                                              mut ident: Ident,
 -                                              ns: Namespace,
 -                                              record_used: bool,
 -                                              force: bool,
 -                                              is_attr: bool,
 -                                              path_span: Span)
 -                                              -> Result<MacroBinding<'a>, Determinacy> {
 +    crate fn resolve_lexical_macro_path_segment(
 +        &mut self,
 +        mut ident: Ident,
 +        ns: Namespace,
 +        record_used: bool,
 +        force: bool,
 +        is_attr: bool,
 +        path_span: Span
 +    ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> {
          // General principles:
          // 1. Not controlled (user-defined) names should have higher priority than controlled names
          //    built into the language or standard library. This way we can add new names into the
          //     m::mac!();
          // }
          // This includes names from globs and from macro expansions.
 -        let mut potentially_ambiguous_result: Option<MacroBinding> = None;
 +        let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None;
  
          enum WhereToResolve<'a> {
              Module(Module<'a>),
                          path_span,
                      );
                      self.current_module = orig_current_module;
 -                    binding.map(MacroBinding::Modern)
 +                    binding.map(|binding| (binding, FromPrelude(false)))
                  }
                  WhereToResolve::MacroPrelude => {
                      match self.macro_prelude.get(&ident.name).cloned() {
 -                        Some(binding) => Ok(MacroBinding::Global(binding)),
 +                        Some(binding) => Ok((binding, FromPrelude(true))),
                          None => Err(Determinacy::Determined),
                      }
                  }
                          let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
                                         ty::Visibility::Public, ident.span, Mark::root())
                                         .to_name_binding(self.arenas);
 -                        Ok(MacroBinding::Global(binding))
 +                        Ok((binding, FromPrelude(true)))
                      } else {
                          Err(Determinacy::Determined)
                      }
  
                          let binding = (crate_root, ty::Visibility::Public,
                                         ident.span, Mark::root()).to_name_binding(self.arenas);
 -                        Ok(MacroBinding::Global(binding))
 +                        Ok((binding, FromPrelude(true)))
                      } else {
                          Err(Determinacy::Determined)
                      }
                      if use_prelude && is_known_tool(ident.name) {
                          let binding = (Def::ToolMod, ty::Visibility::Public,
                                         ident.span, Mark::root()).to_name_binding(self.arenas);
 -                        Ok(MacroBinding::Global(binding))
 +                        Ok((binding, FromPrelude(true)))
                      } else {
                          Err(Determinacy::Determined)
                      }
                                  false,
                                  path_span,
                              ) {
 -                                result = Ok(MacroBinding::Global(binding));
 +                                result = Ok((binding, FromPrelude(true)));
                              }
                          }
                      }
                              self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
                          let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
                                         ident.span, Mark::root()).to_name_binding(self.arenas);
 -                        Ok(MacroBinding::Global(binding))
 +                        Ok((binding, FromPrelude(true)))
                      } else {
                          Err(Determinacy::Determined)
                      }
                          return Ok(result);
                      }
  
 -                    let binding = result.binding();
 -
                      // Found a solution that is ambiguous with a previously found solution.
                      // Push an ambiguity error for later reporting and
                      // return something for better recovery.
                      if let Some(previous_result) = potentially_ambiguous_result {
 -                        if binding.def() != previous_result.binding().def() {
 +                        if result.0.def() != previous_result.0.def() {
                              self.ambiguity_errors.push(AmbiguityError {
                                  span: path_span,
                                  name: ident.name,
 -                                b1: previous_result.binding(),
 -                                b2: binding,
 +                                b1: previous_result.0,
 +                                b2: result.0,
                                  lexical: true,
                              });
                              return Ok(previous_result);
                      // Found a solution that's not an ambiguity yet, but is "suspicious" and
                      // can participate in ambiguities later on.
                      // Remember it and go search for other solutions in outer scopes.
 -                    if binding.is_glob_import() || binding.expansion != Mark::root() {
 +                    if result.0.is_glob_import() || result.0.expansion != Mark::root() {
                          potentially_ambiguous_result = Some(result);
  
                          continue_search!();
              let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom),
                             ty::Visibility::Public, ident.span, Mark::root())
                             .to_name_binding(self.arenas);
 -            Ok(MacroBinding::Global(binding))
 +            Ok((binding, FromPrelude(true)))
          } else {
              Err(determinacy)
          }
      }
  
 -    pub fn resolve_legacy_scope(&mut self,
 -                                mut scope: &'a Cell<LegacyScope<'a>>,
 -                                ident: Ident,
 -                                record_used: bool)
 -                                -> Option<MacroBinding<'a>> {
 +    crate fn resolve_legacy_scope(&mut self,
 +                                  mut scope: &'a Cell<LegacyScope<'a>>,
 +                                  ident: Ident,
 +                                  record_used: bool)
 +                                  -> Option<(&'a LegacyBinding<'a>, FromExpansion)> {
          let ident = ident.modern();
          let mut relative_depth: u32 = 0;
 -        let mut binding = None;
          loop {
              match scope.get() {
                  LegacyScope::Empty => break,
                          if record_used && relative_depth > 0 {
                              self.disallowed_shadowing.push(potential_binding);
                          }
 -                        binding = Some(potential_binding);
 -                        break
 +                        return Some((potential_binding, FromExpansion(relative_depth > 0)));
                      }
                      scope = &potential_binding.parent;
                  }
              };
          }
  
 -        let binding = if let Some(binding) = binding {
 -            MacroBinding::Legacy(binding)
 -        } else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() {
 -            MacroBinding::Global(binding)
 -        } else {
 -            return None;
 -        };
 -
 -        Some(binding)
 +        None
      }
  
      pub fn finalize_current_module_macro_resolutions(&mut self) {
              let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, true,
                                                                       kind == MacroKind::Attr, span);
  
 -            let check_consistency = |this: &Self, binding: MacroBinding| {
 +            let check_consistency = |this: &Self, new_def: Def| {
                  if let Some(def) = def {
                      if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
 -                       binding.def_ignoring_ambiguity() != def {
 +                       new_def != def && new_def != Def::Err {
                          // Make sure compilation does not succeed if preferred macro resolution
                          // has changed after the macro had been expanded. In theory all such
                          // situations should be reported as ambiguity errors, so this is span-bug.
              };
  
              match (legacy_resolution, resolution) {
 -                (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
 -                    if legacy_binding.def_id != binding.def_ignoring_ambiguity().def_id() {
 -                        let msg1 = format!("`{}` could refer to the macro defined here", ident);
 -                        let msg2 =
 -                            format!("`{}` could also refer to the macro imported here", ident);
 -                        self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
 -                            .span_note(legacy_binding.span, &msg1)
 -                            .span_note(binding.span, &msg2)
 -                            .emit();
 -                    }
 -                },
                  (None, Err(_)) => {
                      assert!(def.is_none());
                      let bang = if kind == MacroKind::Bang { "!" } else { "" };
                      self.suggest_macro_name(&ident.as_str(), kind, &mut err, span);
                      err.emit();
                  },
 -                (Some(MacroBinding::Modern(_)), _) | (_, Ok(MacroBinding::Legacy(_))) => {
 -                    span_bug!(span, "impossible macro resolution result");
 -                }
 +                (Some((legacy_binding, FromExpansion(from_expansion))),
 +                 Ok((binding, FromPrelude(false)))) |
 +                (Some((legacy_binding, FromExpansion(from_expansion @ true))),
 +                 Ok((binding, FromPrelude(true)))) => {
 +                    if legacy_binding.def() != binding.def_ignoring_ambiguity() {
 +                        self.report_ambiguity_error(
 +                            ident.name, span, true,
 +                            legacy_binding.def(), false, false,
 +                            from_expansion, legacy_binding.span,
 +                            binding.def(), binding.is_import(), binding.is_glob_import(),
 +                            binding.expansion != Mark::root(), binding.span,
 +                        );
 +                    }
 +                },
 +                // OK, non-macro-expanded legacy wins over macro prelude even if defs are different
 +                (Some((legacy_binding, FromExpansion(false))), Ok((_, FromPrelude(true)))) |
                  // OK, unambiguous resolution
 -                (Some(binding), Err(_)) | (None, Ok(binding)) |
 -                // OK, legacy wins over global even if their definitions are different
 -                (Some(binding @ MacroBinding::Legacy(_)), Ok(MacroBinding::Global(_))) |
 -                // OK, modern wins over global even if their definitions are different
 -                (Some(MacroBinding::Global(_)), Ok(binding @ MacroBinding::Modern(_))) => {
 -                    check_consistency(self, binding);
 +                (Some((legacy_binding, _)), Err(_)) => {
 +                    check_consistency(self, legacy_binding.def());
                  }
 -                (Some(MacroBinding::Global(binding1)), Ok(MacroBinding::Global(binding2))) => {
 -                    if binding1.def() != binding2.def() {
 -                        span_bug!(span, "mismatch between same global macro resolutions");
 +                // OK, unambiguous resolution
 +                (None, Ok((binding, FromPrelude(from_prelude)))) => {
 +                    check_consistency(self, binding.def_ignoring_ambiguity());
 +                    if from_prelude {
 +                        self.record_use(ident, MacroNS, binding, span);
 +                        self.err_if_macro_use_proc_macro(ident.name, span, binding);
                      }
 -                    check_consistency(self, MacroBinding::Global(binding1));
 -
 -                    self.record_use(ident, MacroNS, binding1, span);
 -                    self.err_if_macro_use_proc_macro(ident.name, span, binding1);
 -                },
 +                }
              };
          }
      }
          if let Some(suggestion) = suggestion {
              if suggestion != name {
                  if let MacroKind::Bang = kind {
-                     err.span_suggestion(span, "you could try the macro", suggestion.to_string());
+                     err.span_suggestion_with_applicability(
+                         span,
+                         "you could try the macro",
+                         suggestion.to_string(),
+                         Applicability::MaybeIncorrect
+                     );
                  } else {
-                     err.span_suggestion(span, "try", suggestion.to_string());
+                     err.span_suggestion_with_applicability(
+                         span,
+                         "try",
+                         suggestion.to_string(),
+                         Applicability::MaybeIncorrect
+                     );
                  }
              } else {
                  err.help("have you added the `#[macro_use]` on the module/import?");
      /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]`
      fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span,
                                     binding: &NameBinding<'a>) {
 -        let krate = binding.def().def_id().krate;
 +        let krate = match binding.def() {
 +            Def::NonMacroAttr(..) | Def::Err => return,
 +            Def::Macro(def_id, _) => def_id.krate,
 +            _ => unreachable!(),
 +        };
  
          // Plugin-based syntax extensions are exempt from this check
          if krate == BUILTIN_MACROS_CRATE { return; }
              if let Some(span) = span {
                  let found_use = if found_use { "" } else { "\n" };
                  self.session.struct_span_err(err.use_span, err.warn_msg)
-                     .span_suggestion(
+                     .span_suggestion_with_applicability(
                          span,
                          "instead, import the procedural macro like any other item",
                          format!("use {}::{};{}", err.crate_name, err.name, found_use),
+                         Applicability::MachineApplicable
                      ).emit();
              } else {
                  self.session.struct_span_err(err.use_span, err.warn_msg)
index 010ca1f7ab47529005ee6ec5904324e4fcc8217f,7c46cff890e437d37f100864b0ee73800b01a83b..baf1de1d4e678d56b28cf044eade67d490c201d4
@@@ -102,14 -102,14 +102,14 @@@ use rustc::ty::adjustment::{Adjust, Adj
  use rustc::ty::fold::TypeFoldable;
  use rustc::ty::query::Providers;
  use rustc::ty::util::{Representability, IntTypeExt, Discr};
- use errors::{DiagnosticBuilder, DiagnosticId};
+ use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
  
  use require_c_abi_if_variadic;
  use session::{CompileIncomplete, config, Session};
  use TypeAndSubsts;
  use lint;
  use util::common::{ErrorReported, indenter};
 -use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap};
 +use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap};
  
  use std::cell::{Cell, RefCell, Ref, RefMut};
  use rustc_data_structures::sync::Lrc;
@@@ -505,9 -505,6 +505,9 @@@ impl<'gcx, 'tcx> EnclosingBreakables<'g
      }
  }
  
 +#[derive(Debug)]
 +struct PathSeg(DefId, usize);
 +
  pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
      body_id: ast::NodeId,
  
@@@ -879,7 -876,7 +879,7 @@@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCt
          // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
          fcx.check_casts();
  
 -        // Closure and generater analysis may run after fallback
 +        // Closure and generator analysis may run after fallback
          // because they don't constrain other type variables.
          fcx.closure_analyze(body);
          assert!(fcx.deferred_call_resolutions.borrow().is_empty());
@@@ -1375,7 -1372,7 +1375,7 @@@ fn maybe_check_static_with_link_section
      };
      let param_env = ty::ParamEnv::reveal_all();
      if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
 -        let alloc = tcx.const_value_to_allocation(static_);
 +        let alloc = tcx.const_to_allocation(static_);
          if alloc.relocations.len() != 0 {
              let msg = "statics with a custom `#[link_section]` must be a \
                         simple list of bytes on the wasm target with no \
@@@ -2332,7 -2329,7 +2332,7 @@@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '
      // unconstrained floats with f64.
      // Fallback becomes very dubious if we have encountered type-checking errors.
      // In that case, fallback to TyError.
 -    // The return value indicates whether fallback has occured.
 +    // The return value indicates whether fallback has occurred.
      fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
          use rustc::ty::error::UnconstrainedNumeric::Neither;
          use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
                  let sugg_span = tcx.sess.source_map().end_point(expr_sp);
                  // remove closing `)` from the span
                  let sugg_span = sugg_span.shrink_to_lo();
-                 err.span_suggestion(
+                 err.span_suggestion_with_applicability(
                      sugg_span,
                      "expected the unit value `()`; create it with empty parentheses",
-                     String::from("()"));
+                     String::from("()"),
+                     Applicability::MachineApplicable);
              } else {
                  err.span_label(sp, format!("expected {}{} parameter{}",
                                              if variadic {"at least "} else {""},
                          self.tcx.sess.source_map().span_to_snippet(lhs.span),
                          self.tcx.sess.source_map().span_to_snippet(rhs.span))
                      {
-                         err.span_suggestion(expr.span, msg, format!("{} == {}", left, right));
+                         err.span_suggestion_with_applicability(
+                             expr.span,
+                             msg,
+                             format!("{} == {}", left, right),
+                             Applicability::MaybeIncorrect);
                      } else {
                          err.help(msg);
                      }
                                              ast::LitIntType::Unsuffixed) = lit.node {
                                          let snip = tcx.sess.source_map().span_to_snippet(base.span);
                                          if let Ok(snip) = snip {
-                                             err.span_suggestion(expr.span,
-                                                                 "to access tuple elements, use",
-                                                                 format!("{}.{}", snip, i));
+                                             err.span_suggestion_with_applicability(
+                                                 expr.span,
+                                                 "to access tuple elements, use",
+                                                 format!("{}.{}", snip, i),
+                                                 Applicability::MachineApplicable);
                                              needs_note = false;
                                          }
                                      }
      {
          match *qpath {
              hir::QPath::Resolved(ref maybe_qself, ref path) => {
 -                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
 -                let ty = AstConv::def_to_ty(self, opt_self_ty, path, true);
 +                let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
 +                let ty = AstConv::def_to_ty(self, self_ty, path, true);
                  (path.def, ty)
              }
              hir::QPath::TypeRelative(ref qself, ref segment) => {
                  hir::ExprKind::Match(..) |
                  hir::ExprKind::Block(..) => {
                      let sp = self.tcx.sess.source_map().next_point(cause_span);
-                     err.span_suggestion(sp,
-                                         "try adding a semicolon",
-                                         ";".to_string());
+                     err.span_suggestion_with_applicability(
+                         sp,
+                         "try adding a semicolon",
+                         ";".to_string(),
+                         Applicability::MachineApplicable);
                  }
                  _ => (),
              }
          // haven't set a return type at all (and aren't `fn main()` or an impl).
          match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_nil()) {
              (&hir::FunctionRetTy::DefaultReturn(span), true, true, true) => {
-                 err.span_suggestion(span,
-                                     "try adding a return type",
-                                     format!("-> {} ",
-                                             self.resolve_type_vars_with_obligations(found)));
+                 err.span_suggestion_with_applicability(
+                     span,
+                     "try adding a return type",
+                     format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
+                     Applicability::MachineApplicable);
              }
              (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
                  err.span_label(span, "possibly return type missing here?");
          }
          let original_span = original_sp(last_stmt.span, blk.span);
          let span_semi = original_span.with_lo(original_span.hi() - BytePos(1));
-         err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
+         err.span_suggestion_with_applicability(
+             span_semi,
+             "consider removing this semicolon",
+             "".to_string(),
+             Applicability::MachineApplicable);
      }
  
 -    // Instantiates the given path, which must refer to an item with the given
 -    // number of type parameters and type.
 -    pub fn instantiate_value_path(&self,
 -                                  segments: &[hir::PathSegment],
 -                                  opt_self_ty: Option<Ty<'tcx>>,
 -                                  def: Def,
 -                                  span: Span,
 -                                  node_id: ast::NodeId)
 -                                  -> Ty<'tcx> {
 -        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
 -               segments,
 -               def,
 -               node_id);
 -
 +    fn def_ids_for_path_segments(&self,
 +                                 segments: &[hir::PathSegment],
 +                                 def: Def)
 +                                 -> Vec<PathSeg> {
          // We need to extract the type parameters supplied by the user in
          // the path `path`. Due to the current setup, this is a bit of a
          // tricky-process; the problem is that resolve only tells us the
          // The first step then is to categorize the segments appropriately.
  
          assert!(!segments.is_empty());
 +        let last = segments.len() - 1;
 +
 +        let mut path_segs = vec![];
  
 -        let mut ufcs_associated = None;
 -        let mut type_segment = None;
 -        let mut fn_segment = None;
          match def {
              // Case 1. Reference to a struct/variant constructor.
              Def::StructCtor(def_id, ..) |
              Def::VariantCtor(def_id, ..) => {
                  // Everything but the final segment should have no
                  // parameters at all.
 -                let mut generics = self.tcx.generics_of(def_id);
 -                if let Some(def_id) = generics.parent {
 -                    // Variant and struct constructors use the
 -                    // generics of their parent type definition.
 -                    generics = self.tcx.generics_of(def_id);
 -                }
 -                type_segment = Some((segments.last().unwrap(), generics));
 +                let generics = self.tcx.generics_of(def_id);
 +                // Variant and struct constructors use the
 +                // generics of their parent type definition.
 +                let generics_def_id = generics.parent.unwrap_or(def_id);
 +                path_segs.push(PathSeg(generics_def_id, last));
              }
  
              // Case 2. Reference to a top-level value.
              Def::Fn(def_id) |
              Def::Const(def_id) |
              Def::Static(def_id, _) => {
 -                fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id)));
 +                path_segs.push(PathSeg(def_id, last));
              }
  
              // Case 3. Reference to a method or associated const.
 +            Def::Method(def_id) |
 +            Def::AssociatedConst(def_id) => {
 +                if segments.len() >= 2 {
 +                    let generics = self.tcx.generics_of(def_id);
 +                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
 +                }
 +                path_segs.push(PathSeg(def_id, last));
 +            }
 +
 +            // Case 4. Local variable, no generics.
 +            Def::Local(..) | Def::Upvar(..) => {}
 +
 +            _ => bug!("unexpected definition: {:?}", def),
 +        }
 +
 +        debug!("path_segs = {:?}", path_segs);
 +
 +        path_segs
 +    }
 +
 +    // Instantiates the given path, which must refer to an item with the given
 +    // number of type parameters and type.
 +    pub fn instantiate_value_path(&self,
 +                                  segments: &[hir::PathSegment],
 +                                  self_ty: Option<Ty<'tcx>>,
 +                                  def: Def,
 +                                  span: Span,
 +                                  node_id: ast::NodeId)
 +                                  -> Ty<'tcx> {
 +        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
 +               segments,
 +               def,
 +               node_id);
 +
 +        let path_segs = self.def_ids_for_path_segments(segments, def);
 +
 +        let mut ufcs_associated = None;
 +        match def {
              Def::Method(def_id) |
              Def::AssociatedConst(def_id) => {
                  let container = self.tcx.associated_item(def_id).container;
                      }
                      ty::ImplContainer(_) => {}
                  }
 -
 -                let generics = self.tcx.generics_of(def_id);
 -                if segments.len() >= 2 {
 -                    let parent_generics = self.tcx.generics_of(generics.parent.unwrap());
 -                    type_segment = Some((&segments[segments.len() - 2], parent_generics));
 -                } else {
 +                if segments.len() == 1 {
                      // `<T>::assoc` will end up here, and so can `T::assoc`.
 -                    let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
 +                    let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
                      ufcs_associated = Some((container, self_ty));
                  }
 -                fn_segment = Some((segments.last().unwrap(), generics));
              }
 -
 -            // Case 4. Local variable, no generics.
 -            Def::Local(..) | Def::Upvar(..) => {}
 -
 -            _ => bug!("unexpected definition: {:?}", def),
 +            _ => {}
          }
  
 -        debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
 -
          // Now that we have categorized what space the parameters for each
          // segment belong to, let's sort out the parameters that the user
          // provided (if any) into their appropriate spaces. We'll also report
          // errors if type parameters are provided in an inappropriate place.
 -        let poly_segments = type_segment.is_some() as usize +
 -                            fn_segment.is_some() as usize;
 -        AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]);
 +
 +        let mut generic_segs = FxHashSet::default();
 +        for PathSeg(_, index) in &path_segs {
 +            generic_segs.insert(index);
 +        }
 +        AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| {
 +            if !generic_segs.contains(&index) {
 +                Some(seg)
 +            } else {
 +                None
 +            }
 +        }));
  
          match def {
              Def::Local(nid) | Def::Upvar(nid, ..) => {
          // variables. If the user provided some types, we may still need
          // to add defaults. If the user provided *too many* types, that's
          // a problem.
 -        let supress_mismatch = self.check_impl_trait(span, fn_segment);
 -        self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch);
 -        self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch);
  
 -        let (fn_start, has_self) = match (type_segment, fn_segment) {
 -            (_, Some((_, generics))) => {
 -                (generics.parent_count, generics.has_self)
 -            }
 -            (Some((_, generics)), None) => {
 -                (generics.params.len(), generics.has_self)
 -            }
 -            (None, None) => (0, false)
 -        };
 -        // FIXME(varkor): Separating out the parameters is messy.
 -        let mut lifetimes_type_seg = vec![];
 -        let mut types_type_seg = vec![];
 -        let mut infer_types_type_seg = true;
 -        if let Some((seg, _)) = type_segment {
 -            if let Some(ref data) = seg.args {
 -                for arg in &data.args {
 -                    match arg {
 -                        GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt),
 -                        GenericArg::Type(ty) => types_type_seg.push(ty),
 -                    }
 -                }
 +        let mut infer_args_for_err = FxHashSet::default();
 +        for &PathSeg(def_id, index) in &path_segs {
 +            let seg = &segments[index];
 +            let generics = self.tcx.generics_of(def_id);
 +            // Argument-position `impl Trait` is treated as a normal generic
 +            // parameter internally, but we don't allow users to specify the
 +            // parameter's value explicitly, so we have to do some error-
 +            // checking here.
 +            let suppress_errors = AstConv::check_generic_arg_count_for_call(
 +                self.tcx,
 +                span,
 +                &generics,
 +                &seg,
 +                false, // `is_method_call`
 +            );
 +            if suppress_errors {
 +                infer_args_for_err.insert(index);
 +                self.set_tainted_by_errors(); // See issue #53251.
              }
 -            infer_types_type_seg = seg.infer_types;
          }
  
 -        let mut lifetimes_fn_seg = vec![];
 -        let mut types_fn_seg = vec![];
 -        let mut infer_types_fn_seg = true;
 -        if let Some((seg, _)) = fn_segment {
 -            if let Some(ref data) = seg.args {
 -                for arg in &data.args {
 -                    match arg {
 -                        GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt),
 -                        GenericArg::Type(ty) => types_fn_seg.push(ty),
 -                    }
 -                }
 -            }
 -            infer_types_fn_seg = seg.infer_types;
 -        }
 +        let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
 +            self.tcx.generics_of(*def_id).has_self
 +        }).unwrap_or(false);
  
 -        let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
 -            let mut i = param.index as usize;
 +        let def_id = def.def_id();
  
 -            let (segment, lifetimes, types, infer_types) = if i < fn_start {
 -                if let GenericParamDefKind::Type { .. } = param.kind {
 -                    // Handle Self first, so we can adjust the index to match the AST.
 -                    if has_self && i == 0 {
 -                        return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
 -                            self.var_for_def(span, param)
 -                        });
 +        let substs = AstConv::create_substs_for_generic_args(
 +            self.tcx,
 +            def_id,
 +            &[][..],
 +            has_self,
 +            self_ty,
 +            // Provide the generic args, and whether types should be inferred.
 +            |def_id| {
 +                if let Some(&PathSeg(_, index)) = path_segs.iter().find(|&PathSeg(did, _)| {
 +                    *did == def_id
 +                }) {
 +                    // If we've encountered an `impl Trait`-related error, we're just
 +                    // going to infer the arguments for better error messages.
 +                    if !infer_args_for_err.contains(&index) {
 +                        // Check whether the user has provided generic arguments.
 +                        if let Some(ref data) = segments[index].args {
 +                            return (Some(data), segments[index].infer_types);
 +                        }
                      }
 +                    return (None, segments[index].infer_types);
                  }
 -                i -= has_self as usize;
 -                (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg)
 -            } else {
 -                i -= fn_start;
 -                (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg)
 -            };
  
 -            match param.kind {
 -                GenericParamDefKind::Lifetime => {
 -                    if let Some(lifetime) = lifetimes.get(i) {
 -                        AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
 -                    } else {
 -                        self.re_infer(span, Some(param)).unwrap().into()
 +                (None, true)
 +            },
 +            // Provide substitutions for parameters for which (valid) arguments have been provided.
 +            |param, arg| {
 +                match (&param.kind, arg) {
 +                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
 +                        AstConv::ast_region_to_region(self, lt, Some(param)).into()
 +                    }
 +                    (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
 +                        self.to_ty(ty).into()
                      }
 +                    _ => unreachable!(),
                  }
 -                GenericParamDefKind::Type { .. } => {
 -                    // Skip over the lifetimes in the same segment.
 -                    if let Some((_, generics)) = segment {
 -                        i -= generics.own_counts().lifetimes;
 +            },
 +            // Provide substitutions for parameters for which arguments are inferred.
 +            |substs, param, infer_types| {
 +                match param.kind {
 +                    GenericParamDefKind::Lifetime => {
 +                        self.re_infer(span, Some(param)).unwrap().into()
                      }
 -
 -                    let has_default = match param.kind {
 -                        GenericParamDefKind::Type { has_default, .. } => has_default,
 -                        _ => unreachable!()
 -                    };
 -
 -                    if let Some(ast_ty) = types.get(i) {
 -                        // A provided type parameter.
 -                        self.to_ty(ast_ty).into()
 -                    } else if !infer_types && has_default {
 -                        // No type parameter provided, but a default exists.
 -                        let default = self.tcx.type_of(param.def_id);
 -                        self.normalize_ty(
 -                            span,
 -                            default.subst_spanned(self.tcx, substs, Some(span))
 -                        ).into()
 -                    } else {
 -                        // No type parameters were provided, we can infer all.
 -                        // This can also be reached in some error cases:
 -                        // We prefer to use inference variables instead of
 -                        // TyError to let type inference recover somewhat.
 -                        self.var_for_def(span, param)
 +                    GenericParamDefKind::Type { has_default, .. } => {
 +                        if !infer_types && has_default {
 +                            // If we have a default, then we it doesn't matter that we're not
 +                            // inferring the type arguments: we provide the default where any
 +                            // is missing.
 +                            let default = self.tcx.type_of(param.def_id);
 +                            self.normalize_ty(
 +                                span,
 +                                default.subst_spanned(self.tcx, substs.unwrap(), Some(span))
 +                            ).into()
 +                        } else {
 +                            // If no type arguments were provided, we have to infer them.
 +                            // This case also occurs as a result of some malformed input, e.g.
 +                            // a lifetime argument being given instead of a type paramter.
 +                            // Using inference instead of `TyError` gives better error messages.
 +                            self.var_for_def(span, param)
 +                        }
                      }
                  }
 -            }
 -        });
 +            },
 +        );
  
          // The things we are substituting into the type should not contain
          // escaping late-bound regions, and nor should the base type scheme.
 -        let ty = self.tcx.type_of(def.def_id());
 +        let ty = self.tcx.type_of(def_id);
          assert!(!substs.has_escaping_regions());
          assert!(!ty.has_escaping_regions());
  
          // Add all the obligations that are required, substituting and
          // normalized appropriately.
 -        let bounds = self.instantiate_bounds(span, def.def_id(), &substs);
 +        let bounds = self.instantiate_bounds(span, def_id, &substs);
          self.add_obligations_for_parameters(
 -            traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())),
 +            traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
              &bounds);
  
          // Substitute the values for the type parameters into the type of
              }
          }
  
 -        self.check_rustc_args_require_const(def.def_id(), node_id, span);
 +        self.check_rustc_args_require_const(def_id, node_id, span);
  
          debug!("instantiate_value_path: type of {:?} is {:?}",
                 node_id,
                                        directly, not through a function pointer");
      }
  
 -    /// Report errors if the provided parameters are too few or too many.
 -    fn check_generic_arg_count(&self,
 -                               span: Span,
 -                               segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
 -                               is_method_call: bool,
 -                               supress_mismatch_error: bool) {
 -        let (lifetimes, types, infer_types, bindings) = segment.map_or(
 -            (vec![], vec![], true, &[][..]),
 -            |(s, _)| {
 -                s.args.as_ref().map_or(
 -                    (vec![], vec![], s.infer_types, &[][..]),
 -                    |data| {
 -                        let (mut lifetimes, mut types) = (vec![], vec![]);
 -                        data.args.iter().for_each(|arg| match arg {
 -                            GenericArg::Lifetime(lt) => lifetimes.push(lt),
 -                            GenericArg::Type(ty) => types.push(ty),
 -                        });
 -                        (lifetimes, types, s.infer_types, &data.bindings[..])
 -                    }
 -                )
 -            });
 -
 -        // Check provided parameters.
 -        let ((ty_required, ty_accepted), lt_accepted) =
 -            segment.map_or(((0, 0), 0), |(_, generics)| {
 -                struct ParamRange {
 -                    required: usize,
 -                    accepted: usize
 -                };
 -
 -                let mut lt_accepted = 0;
 -                let mut ty_params = ParamRange { required: 0, accepted: 0 };
 -                for param in &generics.params {
 -                    match param.kind {
 -                        GenericParamDefKind::Lifetime => lt_accepted += 1,
 -                        GenericParamDefKind::Type { has_default, .. } => {
 -                            ty_params.accepted += 1;
 -                            if !has_default {
 -                                ty_params.required += 1;
 -                            }
 -                        }
 -                    };
 -                }
 -                if generics.parent.is_none() && generics.has_self {
 -                    ty_params.required -= 1;
 -                    ty_params.accepted -= 1;
 -                }
 -
 -                ((ty_params.required, ty_params.accepted), lt_accepted)
 -            });
 -
 -        let count_type_params = |n| {
 -            format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
 -        };
 -        let expected_text = count_type_params(ty_accepted);
 -        let actual_text = count_type_params(types.len());
 -        if let Some((mut err, span)) = if types.len() > ty_accepted {
 -            // To prevent derived errors to accumulate due to extra
 -            // type parameters, we force instantiate_value_path to
 -            // use inference variables instead of the provided types.
 -            *segment = None;
 -            let span = types[ty_accepted].span;
 -            Some((struct_span_err!(self.tcx.sess, span, E0087,
 -                                  "too many type parameters provided: \
 -                                  expected at most {}, found {}",
 -                                  expected_text, actual_text), span))
 -        } else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
 -            Some((struct_span_err!(self.tcx.sess, span, E0089,
 -                                  "too few type parameters provided: \
 -                                  expected {}, found {}",
 -                                  expected_text, actual_text), span))
 -        } else {
 -            None
 -        } {
 -            self.set_tainted_by_errors(); // #53251
 -            err.span_label(span, format!("expected {}", expected_text)).emit();
 -        }
 -
 -        if !bindings.is_empty() {
 -            AstConv::prohibit_projection(self, bindings[0].span);
 -        }
 -
 -        let infer_lifetimes = lifetimes.len() == 0;
 -        // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
 -        let has_late_bound_lifetime_defs =
 -            segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
 -        if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) {
 -            // Report this as a lint only if no error was reported previously.
 -            let primary_msg = "cannot specify lifetime arguments explicitly \
 -                               if late bound lifetime parameters are present";
 -            let note_msg = "the late bound lifetime parameter is introduced here";
 -            if !is_method_call && (lifetimes.len() > lt_accepted ||
 -                                   lifetimes.len() < lt_accepted && !infer_lifetimes) {
 -                let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
 -                err.span_note(span_late, note_msg);
 -                err.emit();
 -                *segment = None;
 -            } else {
 -                let mut multispan = MultiSpan::from_span(lifetimes[0].span);
 -                multispan.push_span_label(span_late, note_msg.to_string());
 -                self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
 -                                   lifetimes[0].id, multispan, primary_msg);
 -            }
 -            return;
 -        }
 -
 -        let count_lifetime_params = |n| {
 -            format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
 -        };
 -        let expected_text = count_lifetime_params(lt_accepted);
 -        let actual_text = count_lifetime_params(lifetimes.len());
 -        if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
 -            let span = lifetimes[lt_accepted].span;
 -            Some((struct_span_err!(self.tcx.sess, span, E0088,
 -                                  "too many lifetime parameters provided: \
 -                                  expected at most {}, found {}",
 -                                  expected_text, actual_text), span))
 -        } else if lifetimes.len() < lt_accepted && !infer_lifetimes {
 -            Some((struct_span_err!(self.tcx.sess, span, E0090,
 -                                  "too few lifetime parameters provided: \
 -                                  expected {}, found {}",
 -                                  expected_text, actual_text), span))
 -        } else {
 -            None
 -        } {
 -            err.span_label(span, format!("expected {}", expected_text)).emit();
 -        }
 -    }
 -
 -    /// Report error if there is an explicit type parameter when using `impl Trait`.
 -    fn check_impl_trait(&self,
 -                        span: Span,
 -                        segment: Option<(&hir::PathSegment, &ty::Generics)>)
 -                        -> bool {
 -        let segment = segment.map(|(path_segment, generics)| {
 -            let explicit = !path_segment.infer_types;
 -            let impl_trait = generics.params.iter().any(|param| match param.kind {
 -                ty::GenericParamDefKind::Type {
 -                    synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
 -                } => true,
 -                _ => false,
 -            });
 -
 -            if explicit && impl_trait {
 -                let mut err = struct_span_err! {
 -                    self.tcx.sess,
 -                    span,
 -                    E0632,
 -                    "cannot provide explicit type parameters when `impl Trait` is \
 -                    used in argument position."
 -                };
 -
 -                err.emit();
 -            }
 -
 -            impl_trait
 -        });
 -
 -        segment.unwrap_or(false)
 -    }
 -
      // Resolves `typ` by a single level if `typ` is a type variable.
      // If no resolution is possible, then an error is reported.
      // Numeric inference variables may be left unresolved.
index bebf20b1a3855b1ef115b89a52deb244d23ea53e,a77feae2733f4b086db0cdbb7c02d106355ed52e..b23c2ec3db1011437ac717d9212794b410fbd8c7
@@@ -22,6 -22,7 +22,7 @@@ use syntax::ptr::P
  use syntax::symbol::Symbol;
  use syntax::tokenstream;
  use syntax_pos::{MultiSpan, Span, DUMMY_SP};
+ use errors::Applicability;
  
  use std::borrow::Cow;
  use std::collections::hash_map::Entry;
@@@ -117,7 -118,7 +118,7 @@@ struct Context<'a, 'b: 'a> 
      invalid_refs: Vec<(usize, usize)>,
      /// Spans of all the formatting arguments, in order.
      arg_spans: Vec<Span>,
 -    /// Wether this formatting string is a literal or it comes from a macro.
 +    /// Whether this formatting string is a literal or it comes from a macro.
      is_literal: bool,
  }
  
@@@ -791,10 -792,11 +792,11 @@@ pub fn expand_preparsed_format_args(ecx
                  0 => "{}".to_string(),
                  _ => format!("{}{{}}", "{} ".repeat(args.len())),
              };
-             err.span_suggestion(
+             err.span_suggestion_with_applicability(
                  fmt_sp.shrink_to_lo(),
                  "you might be missing a string literal to format with",
                  format!("\"{}\", ", sugg_fmt),
+                 Applicability::MaybeIncorrect,
              );
              err.emit();
              return DummyResult::raw_expr(sp);