diff options
| author | bors <bors@rust-lang.org> | 2020-01-07 21:23:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-01-07 21:23:19 +0000 |
| commit | 7e393b5b3b543d355ae16c1940cf98b6c7fcb8aa (patch) | |
| tree | 477d03a6fbbd67c1250254a48e3b3d8dad433d96 /src/librustc/infer | |
| parent | 85976442558bf2d09cec3aa49c9c9ba86fb15c1f (diff) | |
| parent | 700ac84eae77e95bbc6e8276a4f4ad102d6e83e5 (diff) | |
| download | rust-7e393b5b3b543d355ae16c1940cf98b6c7fcb8aa.tar.gz rust-7e393b5b3b543d355ae16c1940cf98b6c7fcb8aa.zip | |
Auto merge of #67970 - cjgillot:inherent, r=Centril
Minimize dependencies on trait and infer inside librustc Split from #67953 All commits should pass check on their own. r? @Centril
Diffstat (limited to 'src/librustc/infer')
| -rw-r--r-- | src/librustc/infer/error_reporting/mod.rs | 381 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs | 3 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/note.rs | 105 | ||||
| -rw-r--r-- | src/librustc/infer/opaque_types/mod.rs | 78 | ||||
| -rw-r--r-- | src/librustc/infer/outlives/env.rs | 2 | ||||
| -rw-r--r-- | src/librustc/infer/outlives/free_region_map.rs | 96 | ||||
| -rw-r--r-- | src/librustc/infer/outlives/mod.rs | 1 |
7 files changed, 338 insertions, 328 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 90f546113c1..f262672fdc8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -53,6 +53,8 @@ use crate::hir::map; use crate::infer::opaque_types; use crate::infer::{self, SuppressRegionErrors}; use crate::middle::region; +use crate::traits::error_reporting::report_object_safety_error; +use crate::traits::object_safety_violations; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; @@ -79,212 +81,209 @@ pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; -impl<'tcx> TyCtxt<'tcx> { - pub fn note_and_explain_region( - self, - region_scope_tree: ®ion::ScopeTree, - err: &mut DiagnosticBuilder<'_>, - prefix: &str, - region: ty::Region<'tcx>, - suffix: &str, - ) { - let (description, span) = match *region { - ty::ReScope(scope) => { - let new_string; - let unknown_scope = || { - format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix) - }; - let span = scope.span(self, region_scope_tree); - let tag = match self.hir().find(scope.hir_id(region_scope_tree)) { - Some(Node::Block(_)) => "block", - Some(Node::Expr(expr)) => match expr.kind { - hir::ExprKind::Call(..) => "call", - hir::ExprKind::MethodCall(..) => "method call", - hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", - hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let", - hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for", - hir::ExprKind::Match(..) => "match", - _ => "expression", - }, - Some(Node::Stmt(_)) => "statement", - Some(Node::Item(it)) => Self::item_scope_tag(&it), - Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it), - Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it), - Some(_) | None => { - err.span_note(span, &unknown_scope()); - return; - } - }; - let scope_decorated_tag = match scope.data { - region::ScopeData::Node => tag, - region::ScopeData::CallSite => "scope of call-site for function", - region::ScopeData::Arguments => "scope of function body", - region::ScopeData::Destruction => { - new_string = format!("destruction scope surrounding {}", tag); - &new_string[..] - } - region::ScopeData::Remainder(first_statement_index) => { - new_string = format!( - "block suffix following statement {}", - first_statement_index.index() - ); - &new_string[..] - } - }; - self.explain_span(scope_decorated_tag, span) - } +pub(super) fn note_and_explain_region( + tcx: TyCtxt<'tcx>, + region_scope_tree: ®ion::ScopeTree, + err: &mut DiagnosticBuilder<'_>, + prefix: &str, + region: ty::Region<'tcx>, + suffix: &str, +) { + let (description, span) = match *region { + ty::ReScope(scope) => { + let new_string; + let unknown_scope = + || format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix); + let span = scope.span(tcx, region_scope_tree); + let tag = match tcx.hir().find(scope.hir_id(region_scope_tree)) { + Some(Node::Block(_)) => "block", + Some(Node::Expr(expr)) => match expr.kind { + hir::ExprKind::Call(..) => "call", + hir::ExprKind::MethodCall(..) => "method call", + hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", + hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let", + hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for", + hir::ExprKind::Match(..) => "match", + _ => "expression", + }, + Some(Node::Stmt(_)) => "statement", + Some(Node::Item(it)) => item_scope_tag(&it), + Some(Node::TraitItem(it)) => trait_item_scope_tag(&it), + Some(Node::ImplItem(it)) => impl_item_scope_tag(&it), + Some(_) | None => { + err.span_note(span, &unknown_scope()); + return; + } + }; + let scope_decorated_tag = match scope.data { + region::ScopeData::Node => tag, + region::ScopeData::CallSite => "scope of call-site for function", + region::ScopeData::Arguments => "scope of function body", + region::ScopeData::Destruction => { + new_string = format!("destruction scope surrounding {}", tag); + &new_string[..] + } + region::ScopeData::Remainder(first_statement_index) => { + new_string = format!( + "block suffix following statement {}", + first_statement_index.index() + ); + &new_string[..] + } + }; + explain_span(tcx, scope_decorated_tag, span) + } - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { - self.msg_span_from_free_region(region) - } + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { + msg_span_from_free_region(tcx, region) + } - ty::ReEmpty => ("the empty lifetime".to_owned(), None), + ty::ReEmpty => ("the empty lifetime".to_owned(), None), - ty::RePlaceholder(_) => (format!("any other region"), None), + ty::RePlaceholder(_) => (format!("any other region"), None), - // FIXME(#13998) RePlaceholder should probably print like - // ReFree rather than dumping Debug output on the user. - // - // We shouldn't really be having unification failures with ReVar - // and ReLateBound though. - ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { - (format!("lifetime {:?}", region), None) - } + // FIXME(#13998) RePlaceholder should probably print like + // ReFree rather than dumping Debug output on the user. + // + // We shouldn't really be having unification failures with ReVar + // and ReLateBound though. + ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + (format!("lifetime {:?}", region), None) + } - // We shouldn't encounter an error message with ReClosureBound. - ty::ReClosureBound(..) => { - bug!("encountered unexpected ReClosureBound: {:?}", region,); - } - }; + // We shouldn't encounter an error message with ReClosureBound. + ty::ReClosureBound(..) => { + bug!("encountered unexpected ReClosureBound: {:?}", region,); + } + }; - TyCtxt::emit_msg_span(err, prefix, description, span, suffix); - } + emit_msg_span(err, prefix, description, span, suffix); +} - pub fn note_and_explain_free_region( - self, - err: &mut DiagnosticBuilder<'_>, - prefix: &str, - region: ty::Region<'tcx>, - suffix: &str, - ) { - let (description, span) = self.msg_span_from_free_region(region); +pub(super) fn note_and_explain_free_region( + tcx: TyCtxt<'tcx>, + err: &mut DiagnosticBuilder<'_>, + prefix: &str, + region: ty::Region<'tcx>, + suffix: &str, +) { + let (description, span) = msg_span_from_free_region(tcx, region); - TyCtxt::emit_msg_span(err, prefix, description, span, suffix); - } + emit_msg_span(err, prefix, description, span, suffix); +} - fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option<Span>) { - match *region { - ty::ReEarlyBound(_) | ty::ReFree(_) => { - self.msg_span_from_early_bound_and_free_regions(region) - } - ty::ReStatic => ("the static lifetime".to_owned(), None), - ty::ReEmpty => ("an empty lifetime".to_owned(), None), - _ => bug!("{:?}", region), +fn msg_span_from_free_region( + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, +) -> (String, Option<Span>) { + match *region { + ty::ReEarlyBound(_) | ty::ReFree(_) => { + msg_span_from_early_bound_and_free_regions(tcx, region) } + ty::ReStatic => ("the static lifetime".to_owned(), None), + ty::ReEmpty => ("an empty lifetime".to_owned(), None), + _ => bug!("{:?}", region), } +} - fn msg_span_from_early_bound_and_free_regions( - self, - region: ty::Region<'tcx>, - ) -> (String, Option<Span>) { - let cm = self.sess.source_map(); - - let scope = region.free_region_binding_scope(self); - let node = self.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); - let tag = match self.hir().find(node) { - Some(Node::Block(_)) | Some(Node::Expr(_)) => "body", - Some(Node::Item(it)) => Self::item_scope_tag(&it), - Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it), - Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it), - _ => unreachable!(), - }; - let (prefix, span) = match *region { - ty::ReEarlyBound(ref br) => { - let mut sp = cm.def_span(self.hir().span(node)); - if let Some(param) = - self.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) - { - sp = param.span; - } - (format!("the lifetime `{}` as defined on", br.name), sp) - } - ty::ReFree(ty::FreeRegion { - bound_region: ty::BoundRegion::BrNamed(_, name), .. - }) => { - let mut sp = cm.def_span(self.hir().span(node)); - if let Some(param) = - self.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) - { - sp = param.span; - } - (format!("the lifetime `{}` as defined on", name), sp) - } - ty::ReFree(ref fr) => match fr.bound_region { - ty::BrAnon(idx) => ( - format!("the anonymous lifetime #{} defined on", idx + 1), - self.hir().span(node), - ), - _ => ( - format!("the lifetime `{}` as defined on", region), - cm.def_span(self.hir().span(node)), - ), - }, - _ => bug!(), - }; - let (msg, opt_span) = self.explain_span(tag, span); - (format!("{} {}", prefix, msg), opt_span) - } - - fn emit_msg_span( - err: &mut DiagnosticBuilder<'_>, - prefix: &str, - description: String, - span: Option<Span>, - suffix: &str, - ) { - let message = format!("{}{}{}", prefix, description, suffix); - - if let Some(span) = span { - err.span_note(span, &message); - } else { - err.note(&message); +fn msg_span_from_early_bound_and_free_regions( + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, +) -> (String, Option<Span>) { + let cm = tcx.sess.source_map(); + + let scope = region.free_region_binding_scope(tcx); + let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); + let tag = match tcx.hir().find(node) { + Some(Node::Block(_)) | Some(Node::Expr(_)) => "body", + Some(Node::Item(it)) => item_scope_tag(&it), + Some(Node::TraitItem(it)) => trait_item_scope_tag(&it), + Some(Node::ImplItem(it)) => impl_item_scope_tag(&it), + _ => unreachable!(), + }; + let (prefix, span) = match *region { + ty::ReEarlyBound(ref br) => { + let mut sp = cm.def_span(tcx.hir().span(node)); + if let Some(param) = + tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) + { + sp = param.span; + } + (format!("the lifetime `{}` as defined on", br.name), sp) } - } - - fn item_scope_tag(item: &hir::Item<'_>) -> &'static str { - match item.kind { - hir::ItemKind::Impl(..) => "impl", - hir::ItemKind::Struct(..) => "struct", - hir::ItemKind::Union(..) => "union", - hir::ItemKind::Enum(..) => "enum", - hir::ItemKind::Trait(..) => "trait", - hir::ItemKind::Fn(..) => "function body", - _ => "item", + ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => { + let mut sp = cm.def_span(tcx.hir().span(node)); + if let Some(param) = + tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) + { + sp = param.span; + } + (format!("the lifetime `{}` as defined on", name), sp) } + ty::ReFree(ref fr) => match fr.bound_region { + ty::BrAnon(idx) => { + (format!("the anonymous lifetime #{} defined on", idx + 1), tcx.hir().span(node)) + } + _ => ( + format!("the lifetime `{}` as defined on", region), + cm.def_span(tcx.hir().span(node)), + ), + }, + _ => bug!(), + }; + let (msg, opt_span) = explain_span(tcx, tag, span); + (format!("{} {}", prefix, msg), opt_span) +} + +fn emit_msg_span( + err: &mut DiagnosticBuilder<'_>, + prefix: &str, + description: String, + span: Option<Span>, + suffix: &str, +) { + let message = format!("{}{}{}", prefix, description, suffix); + + if let Some(span) = span { + err.span_note(span, &message); + } else { + err.note(&message); } +} - fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { - match item.kind { - hir::TraitItemKind::Method(..) => "method body", - hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item", - } +fn item_scope_tag(item: &hir::Item<'_>) -> &'static str { + match item.kind { + hir::ItemKind::Impl(..) => "impl", + hir::ItemKind::Struct(..) => "struct", + hir::ItemKind::Union(..) => "union", + hir::ItemKind::Enum(..) => "enum", + hir::ItemKind::Trait(..) => "trait", + hir::ItemKind::Fn(..) => "function body", + _ => "item", } +} - fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str { - match item.kind { - hir::ImplItemKind::Method(..) => "method body", - hir::ImplItemKind::Const(..) - | hir::ImplItemKind::OpaqueTy(..) - | hir::ImplItemKind::TyAlias(..) => "associated item", - } +fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { + match item.kind { + hir::TraitItemKind::Method(..) => "method body", + hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item", } +} - fn explain_span(self, heading: &str, span: Span) -> (String, Option<Span>) { - let lo = self.sess.source_map().lookup_char_pos(span.lo()); - (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span)) +fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str { + match item.kind { + hir::ImplItemKind::Method(..) => "method body", + hir::ImplItemKind::Const(..) + | hir::ImplItemKind::OpaqueTy(..) + | hir::ImplItemKind::TyAlias(..) => "associated item", } } +fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) { + let lo = tcx.sess.source_map().lookup_char_pos(span.lo()); + (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span)) +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_region_errors( &self, @@ -1489,8 +1488,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { FailureCode::Error0038(did) => { - let violations = self.tcx.object_safety_violations(did); - self.tcx.report_object_safety_error(span, did, violations) + let violations = object_safety_violations(self.tcx, did); + report_object_safety_error(self.tcx, span, did, violations) } FailureCode::Error0317(failure_str) => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) @@ -1719,7 +1718,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "consider adding an explicit lifetime bound for `{}`", bound_kind )); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, &format!("{} must be valid for ", labeled_user_string), @@ -1747,7 +1747,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) { let mut err = self.report_inference_failure(var_origin); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "first, the lifetime cannot outlive ", @@ -1771,7 +1772,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { (self.values_str(&sup_trace.values), self.values_str(&sub_trace.values)) { if sub_expected == sup_expected && sub_found == sup_found { - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...but the lifetime must also be valid for ", @@ -1794,7 +1796,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.note_region_origin(&mut err, &sup_origin); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "but, the lifetime must be valid for ", diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 69ebbe1fd36..6c78e70a444 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -1,5 +1,6 @@ //! Error Reporting for static impl Traits. +use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::ty::{BoundRegion, FreeRegion, RegionKind}; @@ -32,7 +33,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); err.span_label(sup_origin.span(), "...but this borrow..."); - let (lifetime, lt_sp_opt) = self.tcx().msg_span_from_free_region(sup_r); + let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r); if let Some(lifetime_sp) = lt_sp_opt { err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime)); } diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 979bcca619c..7919274c373 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -1,3 +1,4 @@ +use crate::infer::error_reporting::note_and_explain_region; use crate::infer::{self, InferCtxt, SubregionOrigin}; use crate::middle::region; use crate::ty::error::TypeError; @@ -167,8 +168,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error(trace, &terr); - self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "..."); - self.tcx.note_and_explain_region( + note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "..."); + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...does not necessarily outlive ", @@ -185,14 +187,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of reference outlives lifetime of \ borrowed content..." ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...the reference is valid for ", sub, "...", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...but the borrowed content is only valid for ", @@ -211,14 +215,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { of captured variable `{}`...", var_name ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...the borrowed pointer is valid for ", sub, "...", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, &format!("...but `{}` is only valid for ", var_name), @@ -230,14 +236,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::InfStackClosure(span) => { let mut err = struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...the closure must be valid for ", sub, "...", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "...but the closure's stack frame is only valid \ @@ -254,7 +262,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { E0315, "cannot invoke closure outside of its lifetime" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the closure is only valid for ", @@ -270,7 +279,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { E0473, "dereference of reference outside its lifetime" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the reference is only valid for ", @@ -288,14 +298,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { enclosing closure", self.tcx.hir().name(id) ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "captured variable is valid for ", sup, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "closure is valid for ", @@ -311,7 +323,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { E0475, "index of slice outside its lifetime" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the slice is only valid for ", @@ -328,14 +341,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of the source pointer does not outlive \ lifetime bound of the object type" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "object type is valid for ", sub, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "source pointer is only valid for ", @@ -354,14 +369,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.ty_to_string(ty) ); match *sub { - ty::ReStatic => self.tcx.note_and_explain_region( + ty::ReStatic => note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "type must satisfy ", sub, "", ), - _ => self.tcx.note_and_explain_region( + _ => note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "type must outlive ", @@ -374,14 +391,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::RelateRegionParamBound(span) => { let mut err = struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "lifetime parameter instantiated with ", sup, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "but lifetime parameter must outlive ", @@ -399,7 +418,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { parameter) is not valid at this point", self.ty_to_string(ty) ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "type must outlive ", @@ -416,7 +436,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of method receiver does not outlive the \ method call" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the receiver is only valid for ", @@ -433,7 +454,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of function argument does not outlive \ the function call" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the function argument is only valid for ", @@ -450,7 +472,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of return value does not outlive the \ function call" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the return value is only valid for ", @@ -467,7 +490,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of operand does not outlive the \ operation" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the operand is only valid for ", @@ -483,7 +507,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { E0484, "reference is not valid at the time of borrow" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the borrow is only valid for ", @@ -500,7 +525,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "automatically reference is not valid at the time \ of borrow" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the automatic borrow is only valid for ", @@ -518,7 +544,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { not valid during the expression: `{}`", self.ty_to_string(t) ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "type is only valid for ", @@ -536,14 +563,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { called while references are dead" ); // FIXME (22171): terms "super/subregion" are suboptimal - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "superregion: ", sup, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "subregion: ", @@ -560,7 +589,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "lifetime of variable does not enclose its \ declaration" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the variable is only valid for ", @@ -576,7 +606,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { E0489, "type/lifetime parameter not in scope here" ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the parameter is only valid for ", @@ -593,14 +624,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "a value of type `{}` is borrowed for too long", self.ty_to_string(ty) ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the type is valid for ", sub, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "but the borrow lasts for ", @@ -618,14 +651,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { than the data it references", self.ty_to_string(ty) ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "the pointer is valid for ", sub, "", ); - self.tcx.note_and_explain_region( + note_and_explain_region( + self.tcx, region_scope_tree, &mut err, "but the referenced data is only valid for ", diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index e9b1ebbd3f6..a22ed940961 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -1,8 +1,9 @@ -use crate::infer::outlives::free_region_map::FreeRegionRelations; +use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region}; use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; use crate::middle::region; use crate::traits::{self, PredicateObligation}; use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::free_region_map::FreeRegionRelations; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt}; use errors::DiagnosticBuilder; @@ -349,7 +350,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("constrain_opaque_type: bounds={:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); - let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates); + let required_region_bounds = + required_region_bounds(tcx, opaque_type, bounds.predicates); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -624,7 +626,8 @@ pub fn unexpected_hidden_region_diagnostic( // // (*) if not, the `tainted_by_errors` flag would be set to // true in any case, so we wouldn't be here at all. - tcx.note_and_explain_free_region( + note_and_explain_free_region( + tcx, &mut err, &format!("hidden type `{}` captures ", hidden_ty), hidden_region, @@ -649,7 +652,8 @@ pub fn unexpected_hidden_region_diagnostic( // If the `region_scope_tree` is available, this is being // invoked from the "region inferencer error". We can at // least report a really cryptic error for now. - tcx.note_and_explain_region( + note_and_explain_region( + tcx, region_scope_tree, &mut err, &format!("hidden type `{}` captures ", hidden_ty), @@ -1130,7 +1134,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone()); + let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1225,3 +1229,67 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir ); res } + +/// Given a set of predicates that apply to an object type, returns +/// the region bounds that the (erased) `Self` type must +/// outlive. Precisely *because* the `Self` type is erased, the +/// parameter `erased_self_ty` must be supplied to indicate what type +/// has been used to represent `Self` in the predicates +/// themselves. This should really be a unique type; `FreshTy(0)` is a +/// popular choice. +/// +/// N.B., in some cases, particularly around higher-ranked bounds, +/// this function returns a kind of conservative approximation. +/// That is, all regions returned by this function are definitely +/// required, but there may be other region bounds that are not +/// returned, as well as requirements like `for<'a> T: 'a`. +/// +/// Requires that trait definitions have been processed so that we can +/// elaborate predicates and walk supertraits. +// +// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's +// what this code should accept. +crate fn required_region_bounds( + tcx: TyCtxt<'tcx>, + erased_self_ty: Ty<'tcx>, + predicates: Vec<ty::Predicate<'tcx>>, +) -> Vec<ty::Region<'tcx>> { + debug!( + "required_region_bounds(erased_self_ty={:?}, predicates={:?})", + erased_self_ty, predicates + ); + + assert!(!erased_self_ty.has_escaping_bound_vars()); + + traits::elaborate_predicates(tcx, predicates) + .filter_map(|predicate| { + match predicate { + ty::Predicate::Projection(..) + | ty::Predicate::Trait(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::WellFormed(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::RegionOutlives(..) + | ty::Predicate::ConstEvaluatable(..) => None, + ty::Predicate::TypeOutlives(predicate) => { + // Search for a bound of the form `erased_self_ty + // : 'a`, but be wary of something like `for<'a> + // erased_self_ty : 'a` (we interpret a + // higher-ranked bound like that as 'static, + // though at present the code in `fulfill.rs` + // considers such bounds to be unsatisfiable, so + // it's kind of a moot point since you could never + // construct such an object, but this seems + // correct even if that code changes). + let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder(); + if t == &erased_self_ty && !r.has_escaping_bound_vars() { + Some(*r) + } else { + None + } + } + } + }) + .collect() +} diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs index 130cffe5022..ee2e629c2fc 100644 --- a/src/librustc/infer/outlives/env.rs +++ b/src/librustc/infer/outlives/env.rs @@ -1,6 +1,6 @@ -use crate::infer::outlives::free_region_map::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::outlives_bounds::{self, OutlivesBound}; +use crate::ty::free_region_map::FreeRegionMap; use crate::ty::{self, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs deleted file mode 100644 index 42f506606e6..00000000000 --- a/src/librustc/infer/outlives/free_region_map.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::ty::{self, Lift, Region, TyCtxt}; -use rustc_data_structures::transitive_relation::TransitiveRelation; - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default, HashStable)] -pub struct FreeRegionMap<'tcx> { - // Stores the relation `a < b`, where `a` and `b` are regions. - // - // Invariant: only free regions like `'x` or `'static` are stored - // in this relation, not scopes. - relation: TransitiveRelation<Region<'tcx>>, -} - -impl<'tcx> FreeRegionMap<'tcx> { - pub fn elements(&self) -> impl Iterator<Item = &Region<'tcx>> { - self.relation.elements() - } - - pub fn is_empty(&self) -> bool { - self.relation.is_empty() - } - - // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`. - // (with the exception that `'static: 'x` is not notable) - pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) { - debug!("relate_regions(sub={:?}, sup={:?})", sub, sup); - if is_free_or_static(sub) && is_free(sup) { - self.relation.add(sub, sup) - } - } - - /// Computes the least-upper-bound of two free regions. In some - /// cases, this is more conservative than necessary, in order to - /// avoid making arbitrary choices. See - /// `TransitiveRelation::postdom_upper_bound` for more details. - pub fn lub_free_regions( - &self, - tcx: TyCtxt<'tcx>, - r_a: Region<'tcx>, - r_b: Region<'tcx>, - ) -> Region<'tcx> { - debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b); - assert!(is_free(r_a)); - assert!(is_free(r_b)); - let result = if r_a == r_b { - r_a - } else { - match self.relation.postdom_upper_bound(&r_a, &r_b) { - None => tcx.mk_region(ty::ReStatic), - Some(r) => *r, - } - }; - debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result); - result - } -} - -/// The NLL region handling code represents free region relations in a -/// slightly different way; this trait allows functions to be abstract -/// over which version is in use. -pub trait FreeRegionRelations<'tcx> { - /// Tests whether `r_a <= r_b`. Both must be free regions or - /// `'static`. - fn sub_free_regions(&self, shorter: ty::Region<'tcx>, longer: ty::Region<'tcx>) -> bool; -} - -impl<'tcx> FreeRegionRelations<'tcx> for FreeRegionMap<'tcx> { - fn sub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> bool { - assert!(is_free_or_static(r_a) && is_free_or_static(r_b)); - if let ty::ReStatic = r_b { - true // `'a <= 'static` is just always true, and not stored in the relation explicitly - } else { - r_a == r_b || self.relation.contains(&r_a, &r_b) - } - } -} - -fn is_free(r: Region<'_>) -> bool { - match *r { - ty::ReEarlyBound(_) | ty::ReFree(_) => true, - _ => false, - } -} - -fn is_free_or_static(r: Region<'_>) -> bool { - match *r { - ty::ReStatic => true, - _ => is_free(r), - } -} - -impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> { - type Lifted = FreeRegionMap<'tcx>; - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<FreeRegionMap<'tcx>> { - self.relation.maybe_map(|&fr| tcx.lift(&fr)).map(|relation| FreeRegionMap { relation }) - } -} diff --git a/src/librustc/infer/outlives/mod.rs b/src/librustc/infer/outlives/mod.rs index e421d6fb692..6fc72470c9f 100644 --- a/src/librustc/infer/outlives/mod.rs +++ b/src/librustc/infer/outlives/mod.rs @@ -1,6 +1,5 @@ //! Various code related to computing outlives relations. pub mod env; -pub mod free_region_map; pub mod obligations; pub mod verify; |
