about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-08-27 12:21:02 +0200
committerCamille GILLOT <gillot.camille@gmail.com>2022-09-13 19:18:23 +0200
commit445841cda32cf9fb95528cfe8d126d0a0e0cb608 (patch)
treedc88d651294afb045b86981bbfc6300f7f2a7c57
parentf76594a0bc0be37d92d9182aa1e7eb1f9e25d54c (diff)
downloadrust-445841cda32cf9fb95528cfe8d126d0a0e0cb608.tar.gz
rust-445841cda32cf9fb95528cfe8d126d0a0e0cb608.zip
Compute explicit MIR params on THIR.
-rw-r--r--compiler/rustc_middle/src/thir.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs65
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs48
-rw-r--r--src/test/ui/thir-tree.stdout1
5 files changed, 86 insertions, 55 deletions
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index c50f8b0eebe..0214610f687 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -78,6 +78,22 @@ thir_with_elements! {
     blocks: BlockId => Block => "b{}",
     exprs: ExprId => Expr<'tcx> => "e{}",
     stmts: StmtId => Stmt<'tcx> => "s{}",
+    params: ParamId => Param<'tcx> => "p{}",
+}
+
+/// Description of a type-checked function parameter.
+#[derive(Clone, Debug, HashStable)]
+pub struct Param<'tcx> {
+    /// The pattern that appears in the parameter list.
+    pub pat: Box<Pat<'tcx>>,
+    /// The possibly inferred type.
+    pub ty: Ty<'tcx>,
+    /// Span of the explicitly provided type, or None if inferred for closures.
+    pub ty_span: Option<Span>,
+    /// Whether this param is `self`, and how it is bound.
+    pub self_kind: Option<hir::ImplicitSelfKind>,
+    /// HirId for lints.
+    pub hir_id: hir::HirId,
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
@@ -548,6 +564,15 @@ impl<'tcx> Pat<'tcx> {
     pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
         Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
     }
+
+    pub fn simple_ident(&self) -> Option<Symbol> {
+        match self.kind {
+            PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
+                Some(name)
+            }
+            _ => None,
+        }
+    }
 }
 
 #[derive(Clone, Debug, HashStable)]
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 505273033a4..b1cb9b9f084 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -568,7 +568,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             _ => {
                 let place_builder = unpack!(block = self.as_place_builder(block, initializer));
-                self.place_into_pattern(block, irrefutable_pat, place_builder, true)
+                self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
             }
         }
     }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b70a4a5d0f8..d44263b4e1b 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,7 +1,6 @@
 pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
-use crate::thir::pattern::pat_from_hir;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_data_structures::fx::FxHashMap;
@@ -9,7 +8,6 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items::LangItem;
 use rustc_hir::{GeneratorKind, ImplicitSelfKind, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -18,8 +16,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
-use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
-use rustc_middle::ty::subst::Subst;
+use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, PatKind, Thir};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -449,10 +446,10 @@ macro_rules! unpack {
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
-struct ArgInfo<'tcx>(
+struct ArgInfo<'thir, 'tcx>(
     Ty<'tcx>,
     Option<Span>,
-    Option<&'tcx hir::Param<'tcx>>,
+    Option<&'thir Param<'tcx>>,
     Option<ImplicitSelfKind>,
 );
 
@@ -510,38 +507,8 @@ fn construct_fn<'tcx>(
         _ => vec![],
     };
 
-    let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
-        let owner_id = tcx.hir().body_owner(body_id);
-        let opt_ty_info;
-        let self_arg;
-        if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
-            opt_ty_info = fn_decl
-                .inputs
-                .get(index)
-                // Make sure that inferred closure args have no type span
-                .and_then(|ty| if arg.pat.span != ty.span { Some(ty.span) } else { None });
-            self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
-                Some(fn_decl.implicit_self)
-            } else {
-                None
-            };
-        } else {
-            opt_ty_info = None;
-            self_arg = None;
-        }
-
-        // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
-        // (as it's created inside the body itself, not passed in from outside).
-        let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
-            let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(arg.span));
-
-            tcx.bound_type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
-        } else {
-            fn_sig.inputs()[index]
-        };
-
-        ArgInfo(ty, opt_ty_info, Some(&arg), self_arg)
-    });
+    let explicit_arguments =
+        thir.params.iter().map(|arg| ArgInfo(arg.ty, arg.ty_span, Some(&arg), arg.self_kind));
 
     let arguments = implicit_argument.into_iter().chain(explicit_arguments);
 
@@ -852,7 +819,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         fn_def_id: LocalDefId,
-        arguments: &[ArgInfo<'tcx>],
+        arguments: &[ArgInfo<'_, 'tcx>],
         argument_scope: region::Scope,
         expr: &Expr<'tcx>,
     ) -> BlockAnd<()> {
@@ -863,9 +830,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
 
             // If this is a simple binding pattern, give debuginfo a nice name.
-            if let Some(arg) = arg_opt && let Some(ident) = arg.pat.simple_ident() {
+            if let Some(arg) = arg_opt && let Some(name) = arg.pat.simple_ident() {
                 self.var_debug_info.push(VarDebugInfo {
-                    name: ident.name,
+                    name,
                     source_info,
                     value: VarDebugInfoContents::Place(arg_local.into()),
                 });
@@ -955,15 +922,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let Some(arg) = arg_opt else {
                 continue;
             };
-            let pat = match tcx.hir().get(arg.pat.hir_id) {
-                Node::Pat(pat) => pat,
-                node => bug!("pattern became {:?}", node),
-            };
-            let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat);
             let original_source_scope = self.source_scope;
-            let span = pattern.span;
+            let span = arg.pat.span;
             self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
-            match pattern.kind {
+            match arg.pat.kind {
                 // Don't introduce extra copies for simple bindings
                 PatKind::Binding {
                     mutability,
@@ -995,15 +957,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     scope = self.declare_bindings(
                         scope,
                         expr.span,
-                        &pattern,
+                        &arg.pat,
                         matches::ArmHasGuard(false),
                         Some((Some(&place), span)),
                     );
                     let place_builder = PlaceBuilder::from(local);
-                    unpack!(
-                        block =
-                            self.place_into_pattern(block, pattern.as_ref(), place_builder, false)
-                    );
+                    unpack!(block = self.place_into_pattern(block, &arg.pat, place_builder, false));
                 }
             }
             self.source_scope = original_source_scope;
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index ae53df1f9b9..8526af75576 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -9,11 +9,12 @@ use rustc_data_structures::steal::Steal;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::HirId;
 use rustc_hir::Node;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
+use rustc_middle::ty::{self, RvalueScopes, Subst, TyCtxt};
 use rustc_span::Span;
 
 pub(crate) fn thir_body<'tcx>(
@@ -27,6 +28,13 @@ pub(crate) fn thir_body<'tcx>(
         return Err(reported);
     }
     let expr = cx.mirror_expr(&body.value);
+
+    let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
+    if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
+        let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
+        cx.thir.params = explicit_params.collect();
+    }
+
     Ok((tcx.alloc_steal_thir(cx.thir), expr))
 }
 
@@ -85,6 +93,44 @@ impl<'tcx> Cx<'tcx> {
         };
         pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
     }
+
+    fn explicit_params<'a>(
+        &'a mut self,
+        owner_id: HirId,
+        fn_decl: &'tcx hir::FnDecl<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
+    ) -> impl Iterator<Item = Param<'tcx>> + 'a {
+        let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
+
+        body.params.iter().enumerate().map(move |(index, param)| {
+            let ty_span = fn_decl
+                .inputs
+                .get(index)
+                // Make sure that inferred closure args have no type span
+                .and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None });
+
+            let self_kind = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
+                Some(fn_decl.implicit_self)
+            } else {
+                None
+            };
+
+            // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
+            // (as it's created inside the body itself, not passed in from outside).
+            let ty = if fn_decl.c_variadic && index == fn_decl.inputs.len() {
+                let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
+
+                self.tcx
+                    .bound_type_of(va_list_did)
+                    .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
+            } else {
+                fn_sig.inputs()[index]
+            };
+
+            let pat = self.pattern_from_hir(param.pat);
+            Param { pat, ty, ty_span, self_kind, hir_id: param.hir_id }
+        })
+    }
 }
 
 impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> {
diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout
index 960b7f7f4dd..5fcdfca18d6 100644
--- a/src/test/ui/thir-tree.stdout
+++ b/src/test/ui/thir-tree.stdout
@@ -54,5 +54,6 @@ Thir {
         },
     ],
     stmts: [],
+    params: [],
 }