diff options
Diffstat (limited to 'compiler/rustc_infer/src')
23 files changed, 163 insertions, 200 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8938ed78a94..7120d5ad934 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -128,7 +128,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( tcx, - region_obligations.iter().map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)), + region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)), region_constraints, ) }); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 67dcb6e708b..8bf1de34a9b 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e319f17b0e6..05556f7d0f9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -68,7 +68,7 @@ use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, }; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; @@ -148,12 +148,10 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Span) { - let sm = tcx.sess.source_map(); - let scope = region.free_region_binding_scope(tcx).expect_local(); match *region { ty::ReEarlyBound(ref br) => { - let mut sp = sm.guess_head_span(tcx.def_span(scope)); + let mut sp = tcx.def_span(scope); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -174,7 +172,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( } else { match fr.bound_region { ty::BoundRegionKind::BrNamed(_, name) => { - let mut sp = sm.guess_head_span(tcx.def_span(scope)); + let mut sp = tcx.def_span(scope); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) { @@ -193,7 +191,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( ), _ => ( format!("the lifetime `{}` as defined here", region), - sm.guess_head_span(tcx.def_span(scope)), + tcx.def_span(scope), ), } } @@ -1540,7 +1538,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 07dcf3876c8..4d29fc46946 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option<hir::BodyId>, failure_span: Span, arg: GenericArg<'tcx>, - // FIXME(#94483): Either use this or remove it. - _impl_candidates: Vec<ty::TraitRef<'tcx>>, error_code: TypeAnnotationNeeded, should_label_span: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { @@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> { }, } +impl<'tcx> InferSource<'tcx> { + fn from_expansion(&self) -> bool { + let source_from_expansion = match self.kind { + InferSourceKind::LetBinding { insert_span, .. } + | InferSourceKind::ClosureArg { insert_span, .. } + | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(), + InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => { + receiver.span.from_expansion() + } + InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => { + data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion) + } + }; + source_from_expansion || self.span.from_expansion() + } +} + impl<'tcx> InferSourceKind<'tcx> { fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { match *self { @@ -604,43 +619,65 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { /// Sources with a small cost are prefer and should result /// in a clearer and idiomatic suggestion. fn source_cost(&self, source: &InferSource<'tcx>) -> usize { - let tcx = self.infcx.tcx; - - fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize { - match arg.unpack() { - GenericArgKind::Lifetime(_) => 0, // erased - GenericArgKind::Type(ty) => ty_cost(ty), - GenericArgKind::Const(_) => 3, // some non-zero value - } + #[derive(Clone, Copy)] + struct CostCtxt<'tcx> { + tcx: TyCtxt<'tcx>, } - fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize { - match ty.kind() { - ty::Closure(..) => 100, - ty::FnDef(..) => 20, - ty::FnPtr(..) => 10, - ty::Infer(..) => 0, - _ => 1, + impl<'tcx> CostCtxt<'tcx> { + fn arg_cost(self, arg: GenericArg<'tcx>) -> usize { + match arg.unpack() { + GenericArgKind::Lifetime(_) => 0, // erased + GenericArgKind::Type(ty) => self.ty_cost(ty), + GenericArgKind::Const(_) => 3, // some non-zero value + } + } + fn ty_cost(self, ty: Ty<'tcx>) -> usize { + match *ty.kind() { + ty::Closure(..) => 1000, + ty::FnDef(..) => 150, + ty::FnPtr(..) => 30, + ty::Adt(def, substs) => { + 5 + self + .tcx + .generics_of(def.did()) + .own_substs_no_defaults(self.tcx, substs) + .iter() + .map(|&arg| self.arg_cost(arg)) + .sum::<usize>() + } + ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(), + ty::Ref(_, ty, _) => 2 + self.ty_cost(ty), + ty::Infer(..) => 0, + _ => 1, + } } } // The sources are listed in order of preference here. - match source.kind { - InferSourceKind::LetBinding { ty, .. } => ty_cost(ty), - InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty), + let tcx = self.infcx.tcx; + let ctx = CostCtxt { tcx }; + let base_cost = match source.kind { + InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), + InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty), InferSourceKind::GenericArg { def_id, generic_args, .. } => { let variant_cost = match tcx.def_kind(def_id) { - DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::<u32>` and friends are ugly. - _ => 12, + // `None::<u32>` and friends are ugly. + DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, + _ => 10, }; - variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::<usize>() + variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { - 20 + substs.iter().map(|arg| arg_cost(arg)).sum::<usize>() + 20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { - 30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } + 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } } - } + }; + + let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 }; + + base_cost + suggestion_may_apply } /// Uses `fn source_cost` to determine whether this inference source is preferable to @@ -648,6 +685,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn update_infer_source(&mut self, new_source: InferSource<'tcx>) { let cost = self.source_cost(&new_source) + self.attempt; + debug!(?cost); self.attempt += 1; if cost < self.infer_source_cost { self.infer_source_cost = cost; @@ -655,6 +693,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } + fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> { + let substs = self.typeck_results.node_substs_opt(hir_id); + self.infcx.resolve_vars_if_possible(substs) + } + fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> { let ty = self.typeck_results.node_type_opt(hir_id); self.infcx.resolve_vars_if_possible(ty) @@ -737,7 +780,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let tcx = self.infcx.tcx; match expr.kind { hir::ExprKind::Path(ref path) => { - if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) { + if let Some(substs) = self.node_substs_opt(expr.hir_id) { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } @@ -765,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { if generics.has_impl_trait() { None? } - let substs = self.typeck_results.node_substs_opt(expr.hir_id)?; + let substs = self.node_substs_opt(expr.hir_id)?; let span = tcx.hir().span(segment.hir_id?); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); InsertableGenericArgs { @@ -980,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { debug!(?args); let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = - generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) + if let Some(argument_index) = generics + .own_substs(substs) + .iter() + .position(|&arg| self.generic_arg_contains_target(arg)) { let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) @@ -1037,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .any(|generics| generics.has_impl_trait()) }; if let ExprKind::MethodCall(path, args, span) = expr.kind - && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) + && let Some(substs) = self.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.infcx.tcx.trait_of_item(def_id).is_some() diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 09430a135a3..02928c4aa57 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_middle::ty::{ - self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor, + self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::Span; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index f6b49e41d4c..91bf9695dfc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::{Span, Symbol}; use std::ops::ControlFlow; @@ -88,7 +88,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 42d52446ab6..b356da0be55 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -5,7 +5,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::TyCtxt; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeVisitable}; use rustc_span::Span; /// Information about the anonymous region we are searching for. @@ -142,7 +142,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn includes_region( &self, - ty: Binder<'tcx, impl TypeFoldable<'tcx>>, + ty: Binder<'tcx, impl TypeVisitable<'tcx>>, region: ty::BoundRegionKind, ) -> bool { let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 082eb1bf111..fad949a3bc6 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,6 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Lift, Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. @@ -14,16 +13,13 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt}; pub(crate) struct RegionRelations<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, - /// The context used for debug messages - pub context: DefId, - /// Free-region relationships. pub free_regions: &'a FreeRegionMap<'tcx>, } impl<'a, 'tcx> RegionRelations<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, context: DefId, free_regions: &'a FreeRegionMap<'tcx>) -> Self { - Self { tcx, context, free_regions } + pub fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { + Self { tcx, free_regions } } pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 024f7409947..84004d2b21f 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -34,7 +34,7 @@ use super::InferCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_middle::infer::unify_key::ToType; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable}; use std::collections::hash_map::Entry; pub struct TypeFreshener<'a, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 68c709a2e24..87fa22b3835 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -120,13 +120,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ) -> LexicalRegionResolutions<'tcx> { let mut var_data = self.construct_var_data(self.tcx()); - // Dorky hack to cause `dump_constraints` to only get called - // if debug mode is enabled: - debug!( - "----() End constraint listing (context={:?}) {:?}---", - self.region_rels.context, - self.dump_constraints(self.region_rels) - ); + if cfg!(debug_assertions) { + self.dump_constraints(); + } let graph = self.construct_graph(); self.expand_givens(&graph); @@ -156,8 +152,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { - debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); + #[instrument(level = "debug", skip(self))] + fn dump_constraints(&self) { for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { debug!("Constraint {} => {:?}", idx, constraint); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6f88b83a473..991fd23ab43 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -15,7 +15,6 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; @@ -26,6 +25,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::visit::TypeVisitable; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; @@ -147,7 +147,7 @@ pub struct InferCtxtInner<'tcx> { /// for each body-id in this map, which will process the /// obligations within. This is expected to be done 'late enough' /// that all type inference variables have been bound and so forth. - region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, + region_obligations: Vec<RegionObligation<'tcx>>, undo_log: InferCtxtUndoLogs<'tcx>, @@ -171,7 +171,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - pub fn region_obligations(&self) -> &[(hir::HirId, RegionObligation<'tcx>)] { + pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] { &self.region_obligations } @@ -319,7 +319,7 @@ pub struct InferCtxt<'a, 'tcx> { } /// See the `error_reporting` module for more details. -#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub enum ValuePairs<'tcx> { Regions(ExpectedFound<ty::Region<'tcx>>), Terms(ExpectedFound<ty::Term<'tcx>>), @@ -1267,7 +1267,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// `resolve_vars_if_possible` as well as `fully_resolve`. pub fn resolve_regions( &self, - region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec<RegionResolutionError<'tcx>> { let (var_infos, data) = { @@ -1286,8 +1285,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .into_infos_and_data() }; - let region_rels = - &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map()); + let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); @@ -1302,12 +1300,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions_and_report_errors( - &self, - region_context: DefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) { - let errors = self.resolve_regions(region_context, outlives_env); + pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + let errors = self.resolve_regions(outlives_env); if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors @@ -1445,7 +1439,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// `resolve_vars_if_possible()`. pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value() } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 846e7f7b921..bab4f3e9e36 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -27,8 +27,8 @@ use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; use rustc_span::Span; use std::fmt::Debug; @@ -810,7 +810,7 @@ struct ScopeInstantiator<'me, 'tcx> { } impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index cc36d6a0a4f..26d689f29ee 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -9,7 +9,8 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor, + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_span::Span; @@ -461,7 +462,7 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 5ea096f5cc2..7234660dbcd 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sso::SsoHashSet; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use smallvec::{smallvec, SmallVec}; #[derive(Debug)] diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 9ddda7b92eb..b897de7315a 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,8 +1,6 @@ use crate::infer::free_regions::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::OutlivesBound; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region}; use super::explicit_outlives_bounds; @@ -31,9 +29,7 @@ pub struct OutlivesEnvironment<'tcx> { pub param_env: ty::ParamEnv<'tcx>, free_region_map: FreeRegionMap<'tcx>, - // Contains, for each body B that we are checking (that is, the fn - // item, but also any nested closures), the set of implied region - // bounds that are in scope in that particular body. + // Contains the implied region bounds in scope for our current body. // // Example: // @@ -43,24 +39,15 @@ pub struct OutlivesEnvironment<'tcx> { // } // body B0 // ``` // - // Here, for body B0, the list would be `[T: 'a]`, because we + // Here, when checking the body B0, the list would be `[T: 'a]`, because we // infer that `T` must outlive `'a` from the implied bounds on the // fn declaration. // - // For the body B1, the list would be `[T: 'a, T: 'b]`, because we + // For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we // also can see that -- within the closure body! -- `T` must // outlive `'b`. This is not necessarily true outside the closure // body, since the closure may never be called. - // - // We collect this map as we descend the tree. We then use the - // results when proving outlives obligations like `T: 'x` later - // (e.g., if `T: 'x` must be proven within the body B1, then we - // know it is true if either `'a: 'x` or `'b: 'x`). - region_bound_pairs_map: FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, - - // Used to compute `region_bound_pairs_map`: contains the set of - // in-scope region-bound pairs thus far. - region_bound_pairs_accum: RegionBoundPairs<'tcx>, + region_bound_pairs: RegionBoundPairs<'tcx>, } /// "Region-bound pairs" tracks outlives relations that are known to @@ -73,8 +60,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { let mut env = OutlivesEnvironment { param_env, free_region_map: Default::default(), - region_bound_pairs_map: Default::default(), - region_bound_pairs_accum: vec![], + region_bound_pairs: Default::default(), }; env.add_outlives_bounds(None, explicit_outlives_bounds(param_env)); @@ -87,62 +73,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { &self.free_region_map } - /// Borrows current value of the `region_bound_pairs`. - pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>> { - &self.region_bound_pairs_map - } - - /// This is a hack to support the old-school regionck, which - /// processes region constraints from the main function and the - /// closure together. In that context, when we enter a closure, we - /// want to be able to "save" the state of the surrounding a - /// function. We can then add implied bounds and the like from the - /// closure arguments into the environment -- these should only - /// apply in the closure body, so once we exit, we invoke - /// `pop_snapshot_post_typeck_child` to remove them. - /// - /// Example: - /// - /// ```ignore (pseudo-rust) - /// fn foo<T>() { - /// callback(for<'a> |x: &'a T| { - /// // ^^^^^^^ not legal syntax, but probably should be - /// // within this closure body, `T: 'a` holds - /// }) - /// } - /// ``` - /// - /// This "containment" of closure's effects only works so well. In - /// particular, we (intentionally) leak relationships between free - /// regions that are created by the closure's bounds. The case - /// where this is useful is when you have (e.g.) a closure with a - /// signature like `for<'a, 'b> fn(x: &'a &'b u32)` -- in this - /// case, we want to keep the relationship `'b: 'a` in the - /// free-region-map, so that later if we have to take `LUB('b, - /// 'a)` we can get the result `'b`. - /// - /// I have opted to keep **all modifications** to the - /// free-region-map, however, and not just those that concern free - /// variables bound in the closure. The latter seems more correct, - /// but it is not the existing behavior, and I could not find a - /// case where the existing behavior went wrong. In any case, it - /// seems like it'd be readily fixed if we wanted. There are - /// similar leaks around givens that seem equally suspicious, to - /// be honest. --nmatsakis - pub fn push_snapshot_pre_typeck_child(&self) -> usize { - self.region_bound_pairs_accum.len() - } - - /// See `push_snapshot_pre_typeck_child`. - pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) { - self.region_bound_pairs_accum.truncate(len); - } - - /// Save the current set of region-bound pairs under the given `body_id`. - pub fn save_implied_bounds(&mut self, body_id: hir::HirId) { - let old = - self.region_bound_pairs_map.insert(body_id, self.region_bound_pairs_accum.clone()); - assert!(old.is_none()); + /// Borrows current `region_bound_pairs`. + pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { + &self.region_bound_pairs } /// Processes outlives bounds that are known to hold, whether from implied or other sources. @@ -164,11 +97,10 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); match outlives_bound { OutlivesBound::RegionSubParam(r_a, param_b) => { - self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b))); + self.region_bound_pairs.push((r_a, GenericKind::Param(param_b))); } OutlivesBound::RegionSubProjection(r_a, projection_b) => { - self.region_bound_pairs_accum - .push((r_a, GenericKind::Projection(projection_b))); + self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b))); } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1c1906f3375..59cf39abe64 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -60,18 +60,16 @@ //! imply that `'b: 'a`. use crate::infer::outlives::components::{push_outlives_components, Component}; +use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::{ self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, }; use crate::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; - -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::undo_log::UndoLogs; -use rustc_hir as hir; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -80,16 +78,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// and later processed by regionck, when full type information is /// available (see `region_obligations` field for more /// information). - pub fn register_region_obligation( - &self, - body_id: hir::HirId, - obligation: RegionObligation<'tcx>, - ) { - debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation); - + #[instrument(level = "debug", skip(self))] + pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) { let mut inner = self.inner.borrow_mut(); inner.undo_log.push(UndoLog::PushRegionObligation); - inner.region_obligations.push((body_id, obligation)); + inner.region_obligations.push(obligation); } pub fn register_region_obligation_with_cause( @@ -109,14 +102,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) }); - self.register_region_obligation( - cause.body_id, - RegionObligation { sup_type, sub_region, origin }, - ); + self.register_region_obligation(RegionObligation { sup_type, sub_region, origin }); } /// Trait queries just want to pass back type obligations "as is" - pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> { + pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } @@ -144,10 +134,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// - `param_env` is the parameter environment for the enclosing function. /// - `body_id` is the body-id whose region obligations are being /// processed. - #[instrument(level = "debug", skip(self, region_bound_pairs_map))] + #[instrument(level = "debug", skip(self, region_bound_pairs))] pub fn process_registered_region_obligations( &self, - region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, + region_bound_pairs: &RegionBoundPairs<'tcx>, param_env: ty::ParamEnv<'tcx>, ) { assert!( @@ -157,7 +147,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let my_region_obligations = self.take_registered_region_obligations(); - for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations { + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { debug!( "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", sup_type, sub_region, origin @@ -165,18 +155,23 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let sup_type = self.resolve_vars_if_possible(sup_type); - if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) { - let outlives = - &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, sup_type, sub_region); - } else { - self.tcx.sess.delay_span_bug( - origin.span(), - &format!("no region-bound-pairs for {:?}", body_id), - ); - } + let outlives = + &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); + outlives.type_must_outlive(origin, sup_type, sub_region); } } + + pub fn check_region_obligations_and_report_errors( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.process_registered_region_obligations( + outlives_env.region_bound_pairs(), + outlives_env.param_env, + ); + + self.resolve_regions_and_report_errors(outlives_env) + } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 9f71ebae99e..772e297b7b4 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -1,7 +1,7 @@ use std::collections::hash_map::Entry; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{ self, error::TypeError, diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 19f83e3377a..c5747ecf702 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -165,7 +165,7 @@ pub struct Verify<'tcx> { pub bound: VerifyBound<'tcx>, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), @@ -272,7 +272,7 @@ pub enum VerifyBound<'tcx> { /// } /// } /// ``` -#[derive(Debug, Copy, Clone, TypeFoldable)] +#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable)] pub struct VerifyIfEq<'tcx> { /// Type which must match the generic `G` pub ty: Ty<'tcx>, diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 1f3cb401314..a6145687429 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,8 +1,9 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; use rustc_middle::mir; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable, TypeVisitor}; -use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use std::ops::ControlFlow; diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index d0c6d8d16eb..b27571275b7 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -4,8 +4,8 @@ use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use std::mem; diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 4eafa3329c3..7e42458fda3 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -23,10 +23,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); - if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); + if trait_item_def_id.is_local() { let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label(span, format!("definition of `{}` from trait", item_name)); + err.span_label( + self.tcx.def_span(trait_item_def_id), + format!("definition of `{}` from trait", item_name), + ); } err.span_label(sp, format!("impl has extra requirement {}", requirement)); diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index b84ed3dc689..932e597509f 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx>, } -#[derive(Clone, TypeFoldable)] +#[derive(Clone, TypeFoldable, TypeVisitable)] pub struct Normalized<'tcx, T> { pub value: T, pub obligations: Vec<PredicateObligation<'tcx>>, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 82ee4bb29e8..573d2d1e330 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,7 +1,8 @@ use crate::traits; use crate::traits::project::Normalized; use rustc_middle::ty; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; +use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use std::fmt; use std::ops::ControlFlow; @@ -68,7 +69,9 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx param_env: self.param_env.try_fold_with(folder)?, }) } +} +impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.predicate.visit_with(visitor)?; self.param_env.visit_with(visitor) |
