* Sized checking in MIR should be a hard error in all borrowck modes
* box operands should be an error even with unsized locals
flow_inits,
move_data,
elements,
flow_inits,
move_data,
elements,
);
if let Some(all_facts) = &mut all_facts {
);
if let Some(all_facts) = &mut all_facts {
use rustc::traits::query::{Fallible, NoSolution};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
use rustc::traits::query::{Fallible, NoSolution};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
-use rustc_errors::Diagnostic;
use std::fmt;
use std::rc::Rc;
use syntax_pos::{Span, DUMMY_SP};
use std::fmt;
use std::rc::Rc;
use syntax_pos::{Span, DUMMY_SP};
/// - `liveness` -- results of a liveness computation on the MIR; used to create liveness
/// constraints for the regions in the types of variables
/// - `flow_inits` -- results of a maybe-init dataflow analysis
/// - `liveness` -- results of a liveness computation on the MIR; used to create liveness
/// constraints for the regions in the types of variables
/// - `flow_inits` -- results of a maybe-init dataflow analysis
-/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
-/// - `errors_buffer` -- errors are sent here for future reporting
+/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysiss
pub(crate) fn type_check<'gcx, 'tcx>(
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'gcx>,
pub(crate) fn type_check<'gcx, 'tcx>(
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'gcx>,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
elements: &Rc<RegionValueElements>,
- errors_buffer: &mut Vec<Diagnostic>,
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let mut constraints = MirTypeckRegionConstraints {
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let mut constraints = MirTypeckRegionConstraints {
®ion_bound_pairs,
Some(implicit_region_bound),
Some(&mut borrowck_context),
®ion_bound_pairs,
Some(implicit_region_bound),
Some(&mut borrowck_context),
|cx| {
cx.equate_inputs_and_outputs(
mir,
|cx| {
cx.equate_inputs_and_outputs(
mir,
region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
implicit_region_bound: Option<ty::Region<'tcx>>,
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
implicit_region_bound: Option<ty::Region<'tcx>>,
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
- errors_buffer: Option<&mut Vec<Diagnostic>>,
mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R,
) -> R where {
let mut checker = TypeChecker::new(
mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R,
) -> R where {
let mut checker = TypeChecker::new(
if !errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
if !errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
- checker.typeck_mir(mir, errors_buffer);
+ checker.typeck_mir(mir);
mir: &Mir<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
mir: &Mir<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
- errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
) {
debug!("check_terminator: {:?}", term);
let tcx = self.tcx();
) {
debug!("check_terminator: {:?}", term);
let tcx = self.tcx();
&sig,
);
let sig = self.normalize(sig, term_location);
&sig,
);
let sig = self.normalize(sig, term_location);
- self.check_call_dest(mir, term, &sig, destination, term_location, errors_buffer);
+ self.check_call_dest(mir, term, &sig, destination, term_location);
self.prove_predicates(
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
self.prove_predicates(
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
sig: &ty::FnSig<'tcx>,
destination: &Option<(Place<'tcx>, BasicBlock)>,
term_location: Location,
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 {
) {
let tcx = self.tcx();
match *destination {
// this check is done at `check_local`.
if self.tcx().features().unsized_locals {
let span = term.source_info.span;
// 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);
+ self.ensure_place_sized(dest_ty, span);
mir: &Mir<'tcx>,
local: Local,
local_decl: &LocalDecl<'tcx>,
mir: &Mir<'tcx>,
local: Local,
local_decl: &LocalDecl<'tcx>,
- errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
) {
match mir.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => {
) {
match mir.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => {
}
// When `#![feature(unsized_locals)]` is enabled, only function calls
}
// When `#![feature(unsized_locals)]` is enabled, only function calls
- // are checked in `check_call_dest`.
+ // and nullary ops are checked in `check_call_dest`.
if !self.tcx().features().unsized_locals {
let span = local_decl.source_info.span;
let ty = local_decl.ty;
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);
+ self.ensure_place_sized(ty, span);
- fn ensure_place_sized(&mut self,
- ty: Ty<'tcx>,
- span: Span,
- errors_buffer: &mut Option<&mut Vec<Diagnostic>>) {
+ fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
let tcx = self.tcx();
// Erase the regions from `ty` to get a global type. The
let tcx = self.tcx();
// Erase the regions from `ty` to get a global type. The
cannot be statically determined",
ty
);
cannot be statically determined",
ty
);
- if let Some(ref mut errors_buffer) = *errors_buffer {
- diag.buffer(errors_buffer);
- } else {
- // we're allowed to use emit() here because the
- // NLL migration will be turned on (and thus
- // errors will need to be buffered) *only if*
- // errors_buffer is Some.
- diag.emit();
- }
+
+ // While this is located in `nll::typeck` this error is not
+ // an NLL error, it's a required check to prevent creation
+ // of unsized rvalues in certain cases:
+ // * operand of a box expression
+ // * callee in a call expression
+ diag.emit();
},
Rvalue::NullaryOp(_, ty) => {
},
Rvalue::NullaryOp(_, ty) => {
+ // Even with unsized locals cannot box an unsized value.
+ if self.tcx().features().unsized_locals {
+ let span = mir.source_info(location).span;
+ self.ensure_place_sized(ty, span);
+ }
+
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().sized_trait().unwrap(),
substs: tcx.mk_substs_trait(ty, &[]),
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().sized_trait().unwrap(),
substs: tcx.mk_substs_trait(ty, &[]),
- fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec<Diagnostic>>) {
+ fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span);
for (local, local_decl) in mir.local_decls.iter_enumerated() {
self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span);
for (local, local_decl) in mir.local_decls.iter_enumerated() {
- self.check_local(mir, local, local_decl, &mut errors_buffer);
+ self.check_local(mir, local, local_decl);
}
for (block, block_data) in mir.basic_blocks().iter_enumerated() {
}
for (block, block_data) in mir.basic_blocks().iter_enumerated() {
location.statement_index += 1;
}
location.statement_index += 1;
}
- self.check_terminator(mir, block_data.terminator(), location, &mut errors_buffer);
+ self.check_terminator(mir, block_data.terminator(), location);
self.check_iscleanup(mir, block_data);
}
}
self.check_iscleanup(mir, block_data);
}
}