]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/astconv.rs
bootstrap: Configurable musl libdir
[rust.git] / src / librustc_typeck / astconv.rs
index 12edfed19c07e409606ec7c507d02cdedd41f487..267f3d9f3ef6e6dc02dbfe7436bc375181174a30 100644 (file)
@@ -8,6 +8,7 @@
 use crate::collect::PlaceholderHirTyCollector;
 use crate::middle::resolve_lifetime as rl;
 use crate::require_c_abi_if_c_variadic;
+use rustc_ast::ast::ParamKindOrd;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::ErrorReported;
@@ -483,8 +484,25 @@ fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static
             arg.descr(),
             kind,
         );
+
+        let kind_ord = match kind {
+            "lifetime" => ParamKindOrd::Lifetime,
+            "type" => ParamKindOrd::Type,
+            "constant" => ParamKindOrd::Const,
+            // It's more concise to match on the string representation, though it means
+            // the match is non-exhaustive.
+            _ => bug!("invalid generic parameter kind {}", kind),
+        };
+        let arg_ord = match arg {
+            GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
+            GenericArg::Type(_) => ParamKindOrd::Type,
+            GenericArg::Const(_) => ParamKindOrd::Const,
+        };
+
         // This note will be true as long as generic parameters are strictly ordered by their kind.
-        err.note(&format!("{} arguments must be provided before {} arguments", kind, arg.descr()));
+        let (first, last) =
+            if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
+        err.note(&format!("{} arguments must be provided before {} arguments", first, last));
         err.emit();
     }
 
@@ -1151,9 +1169,16 @@ fn complain_about_internal_fn_trait(
                             .as_ref()
                             .and_then(|args| args.args.get(0))
                             .and_then(|arg| match arg {
-                                hir::GenericArg::Type(ty) => {
-                                    sess.source_map().span_to_snippet(ty.span).ok()
+                                hir::GenericArg::Type(ty) => match ty.kind {
+                                    hir::TyKind::Tup(t) => t
+                                        .iter()
+                                        .map(|e| sess.source_map().span_to_snippet(e.span))
+                                        .collect::<Result<Vec<_>, _>>()
+                                        .map(|a| a.join(", ")),
+                                    _ => sess.source_map().span_to_snippet(ty.span),
                                 }
+                                .map(|s| format!("({})", s))
+                                .ok(),
                                 _ => None,
                             })
                             .unwrap_or_else(|| "()".to_string()),
@@ -2813,9 +2838,16 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
                 self.res_to_ty(opt_self_ty, path, false)
             }
-            hir::TyKind::Def(item_id, ref lifetimes) => {
-                let did = tcx.hir().local_def_id(item_id.id);
-                self.impl_trait_ty_to_ty(did.to_def_id(), lifetimes)
+            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
+                let opaque_ty = tcx.hir().expect_item(item_id.id);
+                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+
+                match opaque_ty.kind {
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
+                    }
+                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+                }
             }
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
@@ -2868,6 +2900,7 @@ pub fn impl_trait_ty_to_ty(
         &self,
         def_id: DefId,
         lifetimes: &[hir::GenericArg<'_>],
+        replace_parent_lifetimes: bool,
     ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
@@ -2889,9 +2922,18 @@ pub fn impl_trait_ty_to_ty(
                     _ => bug!(),
                 }
             } else {
-                // Replace all parent lifetimes with `'static`.
                 match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+                    // For RPIT (return position impl trait), only lifetimes
+                    // mentioned in the impl Trait predicate are captured by
+                    // the opaque type, so the lifetime parameters from the
+                    // parent item need to be replaced with `'static`.
+                    //
+                    // For `impl Trait` in the types of statics, constants,
+                    // locals and type aliases. These capture all parent
+                    // lifetimes, so they can use their identity subst.
+                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
+                        tcx.lifetimes.re_static.into()
+                    }
                     _ => tcx.mk_param_from_def(param),
                 }
             }