]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/nll/type_check/mod.rs
Remove Ty prefix from Ty{Adt|Array|Slice|RawPtr|Ref|FnDef|FnPtr|Dynamic|Closure|Gener...
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / mod.rs
index eb689f0a9c6c9602f9e8c9f34009a125af601ca5..2fb5861dff44453d4018d75dea29eddd4e0f9d00 100644 (file)
@@ -37,7 +37,7 @@
 use rustc::traits::query::type_op;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
+use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use rustc_errors::Diagnostic;
 use std::fmt;
 use std::rc::Rc;
@@ -320,7 +320,7 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         // constraints on `'a` and `'b`. These constraints
         // would be lost if we just look at the normalized
         // value.
-        if let ty::TyFnDef(def_id, substs) = constant.literal.ty.sty {
+        if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
             let tcx = self.tcx();
             let type_checker = &mut self.cx;
 
@@ -483,7 +483,7 @@ fn sanitize_projection(
             }
             ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
                 ty: match base_ty.sty {
-                    ty::TyArray(inner, size) => {
+                    ty::Array(inner, size) => {
                         let size = size.unwrap_usize(tcx);
                         let min_size = (from as u64) + (to as u64);
                         if let Some(rest_size) = size.checked_sub(min_size) {
@@ -497,12 +497,12 @@ fn sanitize_projection(
                             )
                         }
                     }
-                    ty::TySlice(..) => base_ty,
+                    ty::Slice(..) => base_ty,
                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
                 },
             },
             ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
-                ty::TyAdt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
+                ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
                     if index >= adt_def.variants.len() {
                         PlaceTy::Ty {
                             ty: span_mirbug_and_err!(
@@ -578,8 +578,8 @@ fn field_ty(
                 variant_index,
             } => (&adt_def.variants[variant_index], substs),
             PlaceTy::Ty { ty } => match ty.sty {
-                ty::TyAdt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
-                ty::TyClosure(def_id, substs) => {
+                ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
+                ty::Closure(def_id, substs) => {
                     return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
@@ -587,7 +587,7 @@ fn field_ty(
                         }),
                     }
                 }
-                ty::TyGenerator(def_id, substs, _) => {
+                ty::Generator(def_id, substs, _) => {
                     // Try pre-transform fields first (upvars and current state)
                     if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
                         return Ok(ty);
@@ -602,7 +602,7 @@ fn field_ty(
                         }),
                     };
                 }
-                ty::TyTuple(tys) => {
+                ty::Tuple(tys) => {
                     return match tys.get(field.index()) {
                         Some(&ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
@@ -783,7 +783,7 @@ fn new(
     /// predicates, or otherwise uses the inference context, executes
     /// `op` and then executes all the further obligations that `op`
     /// returns. This will yield a set of outlives constraints amongst
-    /// regions which are extracted and stored as having occured at
+    /// regions which are extracted and stored as having occurred at
     /// `locations`.
     ///
     /// **Any `rustc::infer` operations that might generate region
@@ -877,8 +877,9 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
-                let is_temp = if let Place::Local(l) = place {
-                    !mir.local_decls[*l].is_user_variable.is_some()
+                let is_temp = if let Place::Local(l) = *place {
+                    l != RETURN_PLACE &&
+                    !mir.local_decls[l].is_user_variable.is_some()
                 } else {
                     false
                 };
@@ -902,11 +903,13 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                     );
                 }
                 self.check_rvalue(mir, rv, location);
-                let trait_ref = ty::TraitRef {
-                    def_id: tcx.lang_items().sized_trait().unwrap(),
-                    substs: tcx.mk_substs_trait(place_ty, &[]),
-                };
-                self.prove_trait_ref(trait_ref, location.interesting());
+                if !self.tcx().features().unsized_locals {
+                    let trait_ref = ty::TraitRef {
+                        def_id: tcx.lang_items().sized_trait().unwrap(),
+                        substs: tcx.mk_substs_trait(place_ty, &[]),
+                    };
+                    self.prove_trait_ref(trait_ref, location.interesting());
+                }
             }
             StatementKind::SetDiscriminant {
                 ref place,
@@ -914,7 +917,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
             } => {
                 let place_type = place.ty(mir, tcx).to_ty(tcx);
                 let adt = match place_type.sty {
-                    TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt,
+                    TyKind::Adt(adt, _) if adt.is_enum() => adt,
                     _ => {
                         span_bug!(
                             stmt.source_info.span,
@@ -961,6 +964,7 @@ fn check_terminator(
         mir: &Mir<'tcx>,
         term: &Terminator<'tcx>,
         term_location: Location,
+        errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
     ) {
         debug!("check_terminator: {:?}", term);
         let tcx = self.tcx();
@@ -1028,7 +1032,7 @@ fn check_terminator(
                 let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.sty {
-                    ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx),
+                    ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
                     _ => {
                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
                         return;
@@ -1040,7 +1044,7 @@ fn check_terminator(
                     &sig,
                 );
                 let sig = self.normalize(sig, term_location);
-                self.check_call_dest(mir, term, &sig, destination, term_location);
+                self.check_call_dest(mir, term, &sig, destination, term_location, errors_buffer);
 
                 self.prove_predicates(
                     sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
@@ -1114,12 +1118,25 @@ fn check_call_dest(
         sig: &ty::FnSig<'tcx>,
         destination: &Option<(Place<'tcx>, BasicBlock)>,
         term_location: Location,
+        errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
     ) {
         let tcx = self.tcx();
         match *destination {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
-                let locations = term_location.interesting();
+                let is_temp = if let Place::Local(l) = *dest {
+                    l != RETURN_PLACE &&
+                    !mir.local_decls[l].is_user_variable.is_some()
+                } else {
+                    false
+                };
+
+                let locations = if is_temp {
+                    term_location.boring()
+                } else {
+                    term_location.interesting()
+                };
+
                 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations) {
                     span_mirbug!(
                         self,
@@ -1130,6 +1147,13 @@ fn check_call_dest(
                         terr
                     );
                 }
+
+                // When `#![feature(unsized_locals)]` is not enabled,
+                // this check is done at `check_local`.
+                if self.tcx().features().unsized_locals {
+                    let span = term.source_info.span;
+                    self.ensure_place_sized(dest_ty, span, errors_buffer);
+                }
             }
             None => {
                 // FIXME(canndrew): This is_never should probably be an is_uninhabited
@@ -1296,14 +1320,26 @@ fn check_local(
             LocalKind::Var | LocalKind::Temp => {}
         }
 
-        let span = local_decl.source_info.span;
-        let ty = local_decl.ty;
+        // When `#![feature(unsized_locals)]` is enabled, only function calls
+        // are checked in `check_call_dest`.
+        if !self.tcx().features().unsized_locals {
+            let span = local_decl.source_info.span;
+            let ty = local_decl.ty;
+            self.ensure_place_sized(ty, span, errors_buffer);
+        }
+    }
+
+    fn ensure_place_sized(&mut self,
+                          ty: Ty<'tcx>,
+                          span: Span,
+                          errors_buffer: &mut Option<&mut Vec<Diagnostic>>) {
+        let tcx = self.tcx();
 
         // Erase the regions from `ty` to get a global type.  The
         // `Sized` bound in no way depends on precise regions, so this
         // shouldn't affect `is_sized`.
-        let gcx = self.tcx().global_tcx();
-        let erased_ty = gcx.lift(&self.tcx().erase_regions(&ty)).unwrap();
+        let gcx = tcx.global_tcx();
+        let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
         if !erased_ty.is_sized(gcx.at(span), self.param_env) {
             // in current MIR construction, all non-control-flow rvalue
             // expressions evaluate through `as_temp` or `into` a return
@@ -1436,7 +1472,7 @@ fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Loc
 
                 CastKind::ClosureFnPointer => {
                     let sig = match op.ty(mir, tcx).sty {
-                        ty::TyClosure(def_id, substs) => {
+                        ty::Closure(def_id, substs) => {
                             substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
                         }
                         _ => bug!(),
@@ -1614,7 +1650,7 @@ fn add_reborrow_constraint(
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
-                        ty::TyRef(ref_region, _, mutbl) => {
+                        ty::Ref(ref_region, _, mutbl) => {
                             constraints.outlives_constraints.push(OutlivesConstraint {
                                 sup: ref_region.to_region_vid(),
                                 sub: borrow_region.to_region_vid(),
@@ -1661,11 +1697,11 @@ fn add_reborrow_constraint(
                                 }
                             }
                         }
-                        ty::TyRawPtr(..) => {
+                        ty::RawPtr(..) => {
                             // deref of raw pointer, guaranteed to be valid
                             break;
                         }
-                        ty::TyAdt(def, _) if def.is_box() => {
+                        ty::Adt(def, _) if def.is_box() => {
                             // deref of `Box`, need the base to be valid - propagate
                         }
                         _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
@@ -1825,7 +1861,7 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec<Dia
                 location.statement_index += 1;
             }
 
-            self.check_terminator(mir, block_data.terminator(), location);
+            self.check_terminator(mir, block_data.terminator(), location, &mut errors_buffer);
             self.check_iscleanup(mir, block_data);
         }
     }