X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_mir%2Fborrow_check%2Fnll%2Ftype_check%2Fmod.rs;h=2fb5861dff44453d4018d75dea29eddd4e0f9d00;hb=6f637da50c56a22f745fd056691da8c86824cd9b;hp=a18e2368bf724d55b81f5f5afba76711e8d149d3;hpb=26d7b64237c6daa66064c8583b7aecf534c2a9ae;p=rust.git diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a18e2368bf7..2fb5861dff4 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -18,6 +18,7 @@ use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues}; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; use borrow_check::nll::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; +use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::LocalWithRegion; use borrow_check::nll::ToRegionVid; @@ -36,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; @@ -74,7 +75,7 @@ macro_rules! span_mirbug_and_err { mod constraint_conversion; pub mod free_region_relations; mod input_output; -mod liveness; +crate mod liveness; mod relate_tys; /// Type checks the given `mir` in the context of the inference @@ -115,16 +116,12 @@ pub(crate) fn type_check<'gcx, 'tcx>( universal_regions: &Rc>, location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, - liveness: &LivenessResults, all_facts: &mut Option, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, elements: &Rc, errors_buffer: &mut Vec, -) -> ( - MirTypeckRegionConstraints<'tcx>, - Rc>, -) { +) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); let mut constraints = MirTypeckRegionConstraints { liveness_constraints: LivenessValues::new(elements), @@ -147,7 +144,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( all_facts, ); - { + let (liveness, liveness_map) = { let mut borrowck_context = BorrowCheckContext { universal_regions, location_table, @@ -166,7 +163,6 @@ pub(crate) fn type_check<'gcx, 'tcx>( Some(&mut borrowck_context), Some(errors_buffer), |cx| { - liveness::generate(cx, mir, liveness, flow_inits, move_data); cx.equate_inputs_and_outputs( mir, mir_def_id, @@ -174,14 +170,20 @@ pub(crate) fn type_check<'gcx, 'tcx>( &universal_region_relations, &normalized_inputs_and_output, ); + liveness::generate(cx, mir, flow_inits, move_data) }, - ); - } + ) + }; - (constraints, universal_region_relations) + MirTypeckResults { + constraints, + universal_region_relations, + liveness, + liveness_map, + } } -fn type_check_internal<'a, 'gcx, 'tcx, F>( +fn type_check_internal<'a, 'gcx, 'tcx, R>( infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'gcx>, @@ -190,10 +192,8 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>( implicit_region_bound: Option>, borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, errors_buffer: Option<&mut Vec>, - mut extra: F, -) where - F: FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>), -{ + mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R, +) -> R where { let mut checker = TypeChecker::new( infcx, mir, @@ -214,7 +214,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>( checker.typeck_mir(mir, errors_buffer); } - extra(&mut checker); + extra(&mut checker) } fn mirbug(tcx: TyCtxt, span: Span, msg: &str) { @@ -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 { @@ -655,6 +655,13 @@ struct BorrowCheckContext<'a, 'tcx: 'a> { constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } +crate struct MirTypeckResults<'tcx> { + crate constraints: MirTypeckRegionConstraints<'tcx>, + crate universal_region_relations: Rc>, + crate liveness: LivenessResults, + crate liveness_map: NllLivenessMap, +} + /// A collection of region constraints that must be satisfied for the /// program to be considered well-typed. crate struct MirTypeckRegionConstraints<'tcx> { @@ -776,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 @@ -870,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 }; @@ -895,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, @@ -907,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, @@ -954,6 +964,7 @@ fn check_terminator( mir: &Mir<'tcx>, term: &Terminator<'tcx>, term_location: Location, + errors_buffer: &mut Option<&mut Vec>, ) { debug!("check_terminator: {:?}", term); let tcx = self.tcx(); @@ -1021,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; @@ -1033,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)), @@ -1107,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>, ) { 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, @@ -1123,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 @@ -1289,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>) { + 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 @@ -1429,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!(), @@ -1607,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(), @@ -1654,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), @@ -1818,7 +1861,7 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec