diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index fe9e00f8a60..eda4fc041e8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,7 @@ //! ported to this system, and which relies on string concatenation at the //! time of error detection. -use infer::{self, UnlessNll}; +use infer::{self, SuppressRegionErrors}; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; use super::region_constraints::GenericKind; use super::lexical_region_resolve::RegionResolutionError; @@ -68,7 +68,6 @@ use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TyKind}; use ty::error::TypeError; -use session::config::BorrowckMode; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; @@ -298,20 +297,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &self, region_scope_tree: ®ion::ScopeTree, errors: &Vec>, - unless_nll: UnlessNll, + suppress: SuppressRegionErrors, ) { - debug!("report_region_errors(): {} errors to start", errors.len()); + debug!("report_region_errors(): {} errors to start, suppress = {:?}", errors.len(), suppress); - // If the errors will later be reported by NLL, choose wether to display them or not based - // on the borrowck mode - if unless_nll.0 { - match self.tcx.borrowck_mode() { - // If we're on AST or Migrate mode, report AST region errors - BorrowckMode::Ast | BorrowckMode::Migrate => {}, - // If we're on MIR or Compare mode, don't report AST region errors as they should - // be reported by NLL - BorrowckMode::Compare | BorrowckMode::Mir => return, - } + if suppress.suppressed() { + return; } // try to pre-process the errors, which will group some of them diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index bd8c4962051..dc10ec03fee 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -24,6 +24,7 @@ use middle::free_region::RegionRelations; use middle::lang_items; use middle::region; use rustc_data_structures::unify as ut; +use session::config::BorrowckMode; use std::cell::{Cell, Ref, RefCell, RefMut}; use std::collections::BTreeMap; use std::fmt; @@ -80,15 +81,37 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A flag that is given when running region resolution: if true, it -/// indicates that we should not report the region errors to the user -/// if NLL is enabled, since NLL will also detect them (and do a -/// better job of it). -/// -/// Currently, NLL only runs on HIR bodies, so you should use `false` -/// unless you are region-checking a `hir::Body` (basically, a fn or -/// expression). -pub struct UnlessNll(pub bool); +/// A flag that is used to suppress region errors. This is normally +/// false, but sometimes -- when we are doing region checks that the +/// NLL borrow checker will also do -- it might be set to true. +#[derive(Copy, Clone, Default, Debug)] +pub struct SuppressRegionErrors { + suppressed: bool +} + +impl SuppressRegionErrors { + pub fn suppressed(self) -> bool { + self.suppressed + } + + /// Indicates that the MIR borrowck will repeat these region + /// checks, so we should ignore errors if NLL is (unconditionally) + /// enabled. + pub fn when_nll_is_enabled(tcx: TyCtxt<'_, '_, '_>) -> Self { + match tcx.borrowck_mode() { + // If we're on AST or Migrate mode, report AST region errors + BorrowckMode::Ast | BorrowckMode::Migrate => SuppressRegionErrors { + suppressed: false + }, + + // If we're on MIR or Compare mode, don't report AST region errors as they should + // be reported by NLL + BorrowckMode::Compare | BorrowckMode::Mir => SuppressRegionErrors { + suppressed: true + }, + } + } +} pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -1049,7 +1072,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_context: DefId, region_map: ®ion::ScopeTree, outlives_env: &OutlivesEnvironment<'tcx>, - unless_nll: UnlessNll, + suppress: SuppressRegionErrors, ) { assert!( self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(), @@ -1081,7 +1104,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(region_map, &errors, unless_nll); + self.report_region_errors(region_map, &errors, suppress); } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6c0fe157a2a..406d3a55b1f 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -20,7 +20,7 @@ pub use self::ObligationCauseCode::*; use chalk_engine; use hir; use hir::def_id::DefId; -use infer::UnlessNll; +use infer::SuppressRegionErrors; use infer::outlives::env::OutlivesEnvironment; use middle::region; use mir::interpret::ConstEvalErr; @@ -720,7 +720,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, region_context, ®ion_scope_tree, &outlives_env, - UnlessNll(false), + SuppressRegionErrors::default(), ); let predicates = match infcx.fully_resolve(&predicates) { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index c6e0da309a4..ccaa2f06f01 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -11,7 +11,7 @@ use check::regionck::RegionCtxt; use hir::def_id::DefId; -use rustc::infer::{self, InferOk, UnlessNll}; +use rustc::infer::{self, InferOk, SuppressRegionErrors}; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; @@ -128,7 +128,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // conservative. -nmatsakis let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); - infcx.resolve_regions_and_report_errors(drop_impl_did, ®ion_scope_tree, &outlives_env, UnlessNll(false)); + infcx.resolve_regions_and_report_errors(drop_impl_did, ®ion_scope_tree, &outlives_env, SuppressRegionErrors::default()); Ok(()) }) } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index bc3525adad5..d7d00672853 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -88,8 +88,8 @@ use middle::mem_categorization as mc; use middle::mem_categorization::Categorization; use middle::region; use rustc::hir::def_id::DefId; -use rustc::infer::{self, RegionObligation, UnlessNll}; use rustc::infer::outlives::env::OutlivesEnvironment; +use rustc::infer::{self, RegionObligation, SuppressRegionErrors}; use rustc::ty::adjustment; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; @@ -140,7 +140,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rcx.visit_body(body); rcx.visit_region_obligations(id); } - rcx.resolve_regions_and_report_errors(UnlessNll(true)); + rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); assert!(self.tables.borrow().free_region_map.is_empty()); self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); @@ -162,7 +162,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .add_implied_bounds(self, wf_tys, item_id, span); rcx.outlives_environment.save_implied_bounds(item_id); rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(UnlessNll(false)); + rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default()); } /// Region check a function body. Not invoked on closures, but @@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id)); } - rcx.resolve_regions_and_report_errors(UnlessNll(true)); + rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); // In this mode, we also copy the free-region-map into the // tables of the enclosing fcx. In the other regionck modes @@ -314,7 +314,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { id: ast::NodeId, // the id of the fn itself body: &'gcx hir::Body, span: Span, - ) { + ) { // When we enter a function, we can derive debug!("visit_fn_body(id={})", id); @@ -355,7 +355,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { body_id.node_id, span, ); - self.outlives_environment.save_implied_bounds(body_id.node_id); + self.outlives_environment + .save_implied_bounds(body_id.node_id); self.link_fn_args( region::Scope { id: body.value.hir_id.local_id, @@ -392,7 +393,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.select_all_obligations_or_error(); } - fn resolve_regions_and_report_errors(&self, unless_nll: UnlessNll) { + fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) { self.infcx.process_registered_region_obligations( self.outlives_environment.region_bound_pairs_map(), self.implicit_region_bound, @@ -403,7 +404,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.subject_def_id, &self.region_scope_tree, &self.outlives_environment, - unless_nll, + suppress, ); } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 4def76e8922..db08bf80953 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -11,7 +11,7 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use rustc::infer::UnlessNll; +use rustc::infer::SuppressRegionErrors; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region; use rustc::middle::lang_items::UnsizeTraitLangItem; @@ -397,7 +397,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, impl_did, ®ion_scope_tree, &outlives_env, - UnlessNll(false), + SuppressRegionErrors::default(), ); CoerceUnsizedInfo {