]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/check/gather_locals.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / gather_locals.rs
CommitLineData
1b1a35ee
XL
1use crate::check::{FnCtxt, LocalTy, UserType};
2use rustc_hir as hir;
3use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
4use rustc_hir::PatKind;
5use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
6use rustc_middle::ty::Ty;
7use rustc_span::Span;
8use rustc_trait_selection::traits;
9
10pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
11 fcx: &'a FnCtxt<'a, 'tcx>,
12 parent_id: hir::HirId,
13}
14
15impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
16 pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
17 Self { fcx, parent_id }
18 }
19
20 fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
21 match ty_opt {
22 None => {
23 // Infer the variable's type.
24 let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
25 kind: TypeVariableOriginKind::TypeInference,
26 span,
27 });
28 self.fcx
29 .locals
30 .borrow_mut()
31 .insert(nid, LocalTy { decl_ty: var_ty, revealed_ty: var_ty });
32 var_ty
33 }
34 Some(typ) => {
35 // Take type that the user specified.
36 self.fcx.locals.borrow_mut().insert(nid, typ);
37 typ.revealed_ty
38 }
39 }
40 }
41}
42
43impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
44 type Map = intravisit::ErasedMap<'tcx>;
45
46 fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
47 NestedVisitorMap::None
48 }
49
50 // Add explicitly-declared locals.
51 fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
52 let local_ty = match local.ty {
53 Some(ref ty) => {
54 let o_ty = self.fcx.to_ty(&ty);
55
56 let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
57 self.fcx.instantiate_opaque_types_from_value(self.parent_id, &o_ty, ty.span)
58 } else {
59 o_ty
60 };
61
62 let c_ty = self
63 .fcx
64 .inh
65 .infcx
66 .canonicalize_user_type_annotation(&UserType::Ty(revealed_ty));
67 debug!(
68 "visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
69 ty.hir_id, o_ty, revealed_ty, c_ty
70 );
71 self.fcx
72 .typeck_results
73 .borrow_mut()
74 .user_provided_types_mut()
75 .insert(ty.hir_id, c_ty);
76
77 Some(LocalTy { decl_ty: o_ty, revealed_ty })
78 }
79 None => None,
80 };
81 self.assign(local.span, local.hir_id, local_ty);
82
83 debug!(
84 "local variable {:?} is assigned type {}",
85 local.pat,
86 self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&local.hir_id).unwrap().decl_ty)
87 );
88 intravisit::walk_local(self, local);
89 }
90
91 // Add pattern bindings.
92 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
93 if let PatKind::Binding(_, _, ident, _) = p.kind {
94 let var_ty = self.assign(p.span, p.hir_id, None);
95
96 if !self.fcx.tcx.features().unsized_locals {
97 self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
98 }
99
100 debug!(
101 "pattern binding {} is assigned to {} with type {:?}",
102 ident,
103 self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&p.hir_id).unwrap().decl_ty),
104 var_ty
105 );
106 }
107 intravisit::walk_pat(self, p);
108 }
109
110 // Don't descend into the bodies of nested closures.
111 fn visit_fn(
112 &mut self,
113 _: intravisit::FnKind<'tcx>,
114 _: &'tcx hir::FnDecl<'tcx>,
115 _: hir::BodyId,
116 _: Span,
117 _: hir::HirId,
118 ) {
119 }
120}