Rollup merge of #48682 - spastorino:make_causal_lazy, r=nikomatsakis
[NLL] Make causal tracking lazy Close #46590 cc @nikomatsakis
This commit is contained in:
commit
d7f44ac52c
33 changed files with 1242 additions and 847 deletions
|
@ -138,9 +138,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.explain_span(scope_decorated_tag, span)
|
self.explain_span(scope_decorated_tag, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ReEarlyBound(_) | ty::ReFree(_) => self.msg_span_from_free_region(region),
|
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
|
||||||
|
self.msg_span_from_free_region(region)
|
||||||
ty::ReStatic => ("the static lifetime".to_owned(), None),
|
}
|
||||||
|
|
||||||
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
|
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
|
||||||
|
|
||||||
|
@ -175,6 +175,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option<Span>) {
|
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),
|
||||||
|
_ => bug!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msg_span_from_early_bound_and_free_regions(
|
||||||
|
self,
|
||||||
|
region: ty::Region<'tcx>,
|
||||||
|
) -> (String, Option<Span>) {
|
||||||
let scope = region.free_region_binding_scope(self);
|
let scope = region.free_region_binding_scope(self);
|
||||||
let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
|
let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
|
||||||
let unknown;
|
let unknown;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics;
|
||||||
use middle::allocator::AllocatorKind;
|
use middle::allocator::AllocatorKind;
|
||||||
use middle::dependency_format;
|
use middle::dependency_format;
|
||||||
use session::search_paths::PathKind;
|
use session::search_paths::PathKind;
|
||||||
use session::config::{DebugInfoLevel, OutputType, Epoch};
|
use session::config::{DebugInfoLevel, Epoch, OutputType};
|
||||||
use ty::tls;
|
use ty::tls;
|
||||||
use util::nodemap::{FxHashMap, FxHashSet};
|
use util::nodemap::{FxHashMap, FxHashSet};
|
||||||
use util::common::{duration_to_secs_str, ErrorReported};
|
use util::common::{duration_to_secs_str, ErrorReported};
|
||||||
|
@ -37,7 +37,7 @@ use syntax::parse;
|
||||||
use syntax::parse::ParseSess;
|
use syntax::parse::ParseSess;
|
||||||
use syntax::{ast, codemap};
|
use syntax::{ast, codemap};
|
||||||
use syntax::feature_gate::AttributeType;
|
use syntax::feature_gate::AttributeType;
|
||||||
use syntax_pos::{Span, MultiSpan};
|
use syntax_pos::{MultiSpan, Span};
|
||||||
|
|
||||||
use rustc_back::{LinkerFlavor, PanicStrategy};
|
use rustc_back::{LinkerFlavor, PanicStrategy};
|
||||||
use rustc_back::target::Target;
|
use rustc_back::target::Target;
|
||||||
|
@ -87,7 +87,7 @@ pub struct Session {
|
||||||
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
|
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
|
||||||
pub crate_types: RefCell<Vec<config::CrateType>>,
|
pub crate_types: RefCell<Vec<config::CrateType>>,
|
||||||
pub dependency_formats: RefCell<dependency_format::Dependencies>,
|
pub dependency_formats: RefCell<dependency_format::Dependencies>,
|
||||||
/// The crate_disambiguator is constructed out of all the `-C metadata`
|
/// The crate_disambiguator is constructed out of all the `-C metadata`
|
||||||
/// arguments passed to the compiler. Its value together with the crate-name
|
/// arguments passed to the compiler. Its value together with the crate-name
|
||||||
/// forms a unique global identifier for the crate. It is used to allow
|
/// forms a unique global identifier for the crate. It is used to allow
|
||||||
/// multiple crates with the same name to coexist. See the
|
/// multiple crates with the same name to coexist. See the
|
||||||
|
@ -141,7 +141,6 @@ pub struct Session {
|
||||||
out_of_fuel: Cell<bool>,
|
out_of_fuel: Cell<bool>,
|
||||||
|
|
||||||
// The next two are public because the driver needs to read them.
|
// The next two are public because the driver needs to read them.
|
||||||
|
|
||||||
/// If -zprint-fuel=crate, Some(crate).
|
/// If -zprint-fuel=crate, Some(crate).
|
||||||
pub print_fuel_crate: Option<String>,
|
pub print_fuel_crate: Option<String>,
|
||||||
/// Always set to zero and incremented so that we can print fuel expended by a crate.
|
/// Always set to zero and incremented so that we can print fuel expended by a crate.
|
||||||
|
@ -175,7 +174,7 @@ enum DiagnosticBuilderMethod {
|
||||||
Note,
|
Note,
|
||||||
SpanNote,
|
SpanNote,
|
||||||
SpanSuggestion(String), // suggestion
|
SpanSuggestion(String), // suggestion
|
||||||
// add more variants as needed to support one-time diagnostics
|
// add more variants as needed to support one-time diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid
|
/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid
|
||||||
|
@ -184,7 +183,7 @@ enum DiagnosticBuilderMethod {
|
||||||
pub enum DiagnosticMessageId {
|
pub enum DiagnosticMessageId {
|
||||||
ErrorId(u16), // EXXXX error code as integer
|
ErrorId(u16), // EXXXX error code as integer
|
||||||
LintId(lint::LintId),
|
LintId(lint::LintId),
|
||||||
StabilityId(u32) // issue number
|
StabilityId(u32), // issue number
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static lint::Lint> for DiagnosticMessageId {
|
impl From<&'static lint::Lint> for DiagnosticMessageId {
|
||||||
|
@ -201,33 +200,37 @@ impl Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_warn<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str)
|
sp: S,
|
||||||
-> DiagnosticBuilder<'a> {
|
msg: &str,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_warn(sp, msg)
|
self.diagnostic().struct_span_warn(sp, msg)
|
||||||
}
|
}
|
||||||
pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str,
|
sp: S,
|
||||||
code: DiagnosticId)
|
msg: &str,
|
||||||
-> DiagnosticBuilder<'a> {
|
code: DiagnosticId,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
|
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
|
||||||
}
|
}
|
||||||
pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_warn(msg)
|
self.diagnostic().struct_warn(msg)
|
||||||
}
|
}
|
||||||
pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_err<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str)
|
sp: S,
|
||||||
-> DiagnosticBuilder<'a> {
|
msg: &str,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_err(sp, msg)
|
self.diagnostic().struct_span_err(sp, msg)
|
||||||
}
|
}
|
||||||
pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str,
|
sp: S,
|
||||||
code: DiagnosticId)
|
msg: &str,
|
||||||
-> DiagnosticBuilder<'a> {
|
code: DiagnosticId,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_err_with_code(sp, msg, code)
|
self.diagnostic().struct_span_err_with_code(sp, msg, code)
|
||||||
}
|
}
|
||||||
// FIXME: This method should be removed (every error should have an associated error code).
|
// FIXME: This method should be removed (every error should have an associated error code).
|
||||||
|
@ -241,20 +244,22 @@ impl Session {
|
||||||
) -> DiagnosticBuilder<'a> {
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_err_with_code(msg, code)
|
self.diagnostic().struct_err_with_code(msg, code)
|
||||||
}
|
}
|
||||||
pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str)
|
sp: S,
|
||||||
-> DiagnosticBuilder<'a> {
|
msg: &str,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_fatal(sp, msg)
|
self.diagnostic().struct_span_fatal(sp, msg)
|
||||||
}
|
}
|
||||||
pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
|
pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(
|
||||||
sp: S,
|
&'a self,
|
||||||
msg: &str,
|
sp: S,
|
||||||
code: DiagnosticId)
|
msg: &str,
|
||||||
-> DiagnosticBuilder<'a> {
|
code: DiagnosticId,
|
||||||
|
) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
|
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
|
||||||
}
|
}
|
||||||
pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
||||||
self.diagnostic().struct_fatal(msg)
|
self.diagnostic().struct_fatal(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +272,9 @@ impl Session {
|
||||||
msg: &str,
|
msg: &str,
|
||||||
code: DiagnosticId,
|
code: DiagnosticId,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
self.diagnostic().span_fatal_with_code(sp, msg, code).raise()
|
self.diagnostic()
|
||||||
|
.span_fatal_with_code(sp, msg, code)
|
||||||
|
.raise()
|
||||||
}
|
}
|
||||||
pub fn fatal(&self, msg: &str) -> ! {
|
pub fn fatal(&self, msg: &str) -> ! {
|
||||||
self.diagnostic().fatal(msg).raise()
|
self.diagnostic().fatal(msg).raise()
|
||||||
|
@ -301,7 +308,8 @@ impl Session {
|
||||||
compile_result_from_err_count(self.err_count())
|
compile_result_from_err_count(self.err_count())
|
||||||
}
|
}
|
||||||
pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
|
pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
|
||||||
where F: FnOnce() -> T
|
where
|
||||||
|
F: FnOnce() -> T,
|
||||||
{
|
{
|
||||||
let old_count = self.err_count();
|
let old_count = self.err_count();
|
||||||
let result = f();
|
let result = f();
|
||||||
|
@ -344,24 +352,31 @@ impl Session {
|
||||||
self.diagnostic().unimpl(msg)
|
self.diagnostic().unimpl(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_lint<S: Into<MultiSpan>>(&self,
|
pub fn buffer_lint<S: Into<MultiSpan>>(
|
||||||
lint: &'static lint::Lint,
|
&self,
|
||||||
id: ast::NodeId,
|
lint: &'static lint::Lint,
|
||||||
sp: S,
|
id: ast::NodeId,
|
||||||
msg: &str) {
|
sp: S,
|
||||||
|
msg: &str,
|
||||||
|
) {
|
||||||
match *self.buffered_lints.borrow_mut() {
|
match *self.buffered_lints.borrow_mut() {
|
||||||
Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(),
|
Some(ref mut buffer) => {
|
||||||
msg, BuiltinLintDiagnostics::Normal),
|
buffer.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
|
||||||
|
}
|
||||||
None => bug!("can't buffer lints after HIR lowering"),
|
None => bug!("can't buffer lints after HIR lowering"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(&self,
|
pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
|
||||||
lint: &'static lint::Lint, id: ast::NodeId, sp: S,
|
&self,
|
||||||
msg: &str, diagnostic: BuiltinLintDiagnostics) {
|
lint: &'static lint::Lint,
|
||||||
|
id: ast::NodeId,
|
||||||
|
sp: S,
|
||||||
|
msg: &str,
|
||||||
|
diagnostic: BuiltinLintDiagnostics,
|
||||||
|
) {
|
||||||
match *self.buffered_lints.borrow_mut() {
|
match *self.buffered_lints.borrow_mut() {
|
||||||
Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(),
|
Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg, diagnostic),
|
||||||
msg, diagnostic),
|
|
||||||
None => bug!("can't buffer lints after HIR lowering"),
|
None => bug!("can't buffer lints after HIR lowering"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,7 +388,7 @@ impl Session {
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
self.next_node_id.set(ast::NodeId::new(next));
|
self.next_node_id.set(ast::NodeId::new(next));
|
||||||
}
|
}
|
||||||
None => bug!("Input too large, ran out of node ids!")
|
None => bug!("Input too large, ran out of node ids!"),
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
|
@ -387,24 +402,27 @@ impl Session {
|
||||||
|
|
||||||
/// Analogous to calling methods on the given `DiagnosticBuilder`, but
|
/// Analogous to calling methods on the given `DiagnosticBuilder`, but
|
||||||
/// deduplicates on lint ID, span (if any), and message for this `Session`
|
/// deduplicates on lint ID, span (if any), and message for this `Session`
|
||||||
fn diag_once<'a, 'b>(&'a self,
|
fn diag_once<'a, 'b>(
|
||||||
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
&'a self,
|
||||||
method: DiagnosticBuilderMethod,
|
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
||||||
msg_id: DiagnosticMessageId,
|
method: DiagnosticBuilderMethod,
|
||||||
message: &str,
|
msg_id: DiagnosticMessageId,
|
||||||
span_maybe: Option<Span>) {
|
message: &str,
|
||||||
|
span_maybe: Option<Span>,
|
||||||
|
) {
|
||||||
let id_span_message = (msg_id, span_maybe, message.to_owned());
|
let id_span_message = (msg_id, span_maybe, message.to_owned());
|
||||||
let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message);
|
let fresh = self.one_time_diagnostics
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(id_span_message);
|
||||||
if fresh {
|
if fresh {
|
||||||
match method {
|
match method {
|
||||||
DiagnosticBuilderMethod::Note => {
|
DiagnosticBuilderMethod::Note => {
|
||||||
diag_builder.note(message);
|
diag_builder.note(message);
|
||||||
},
|
}
|
||||||
DiagnosticBuilderMethod::SpanNote => {
|
DiagnosticBuilderMethod::SpanNote => {
|
||||||
let span = span_maybe.expect("span_note needs a span");
|
let span = span_maybe.expect("span_note needs a span");
|
||||||
diag_builder.span_note(span, message);
|
diag_builder.span_note(span, message);
|
||||||
},
|
}
|
||||||
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
|
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
|
||||||
let span = span_maybe.expect("span_suggestion needs a span");
|
let span = span_maybe.expect("span_suggestion needs a span");
|
||||||
diag_builder.span_suggestion(span, message, suggestion);
|
diag_builder.span_suggestion(span, message, suggestion);
|
||||||
|
@ -413,37 +431,66 @@ impl Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diag_span_note_once<'a, 'b>(&'a self,
|
pub fn diag_span_note_once<'a, 'b>(
|
||||||
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
&'a self,
|
||||||
msg_id: DiagnosticMessageId, span: Span, message: &str) {
|
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
||||||
self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote,
|
msg_id: DiagnosticMessageId,
|
||||||
msg_id, message, Some(span));
|
span: Span,
|
||||||
|
message: &str,
|
||||||
|
) {
|
||||||
|
self.diag_once(
|
||||||
|
diag_builder,
|
||||||
|
DiagnosticBuilderMethod::SpanNote,
|
||||||
|
msg_id,
|
||||||
|
message,
|
||||||
|
Some(span),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diag_note_once<'a, 'b>(&'a self,
|
pub fn diag_note_once<'a, 'b>(
|
||||||
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
&'a self,
|
||||||
msg_id: DiagnosticMessageId, message: &str) {
|
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
||||||
self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None);
|
msg_id: DiagnosticMessageId,
|
||||||
|
message: &str,
|
||||||
|
) {
|
||||||
|
self.diag_once(
|
||||||
|
diag_builder,
|
||||||
|
DiagnosticBuilderMethod::Note,
|
||||||
|
msg_id,
|
||||||
|
message,
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diag_span_suggestion_once<'a, 'b>(&'a self,
|
pub fn diag_span_suggestion_once<'a, 'b>(
|
||||||
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
&'a self,
|
||||||
msg_id: DiagnosticMessageId,
|
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
||||||
span: Span,
|
msg_id: DiagnosticMessageId,
|
||||||
message: &str,
|
span: Span,
|
||||||
suggestion: String) {
|
message: &str,
|
||||||
self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanSuggestion(suggestion),
|
suggestion: String,
|
||||||
msg_id, message, Some(span));
|
) {
|
||||||
|
self.diag_once(
|
||||||
|
diag_builder,
|
||||||
|
DiagnosticBuilderMethod::SpanSuggestion(suggestion),
|
||||||
|
msg_id,
|
||||||
|
message,
|
||||||
|
Some(span),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
|
pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
|
||||||
self.parse_sess.codemap()
|
self.parse_sess.codemap()
|
||||||
}
|
}
|
||||||
pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
|
pub fn verbose(&self) -> bool {
|
||||||
pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
|
self.opts.debugging_opts.verbose
|
||||||
|
}
|
||||||
|
pub fn time_passes(&self) -> bool {
|
||||||
|
self.opts.debugging_opts.time_passes
|
||||||
|
}
|
||||||
pub fn profile_queries(&self) -> bool {
|
pub fn profile_queries(&self) -> bool {
|
||||||
self.opts.debugging_opts.profile_queries ||
|
self.opts.debugging_opts.profile_queries
|
||||||
self.opts.debugging_opts.profile_queries_and_keys
|
|| self.opts.debugging_opts.profile_queries_and_keys
|
||||||
}
|
}
|
||||||
pub fn profile_queries_and_keys(&self) -> bool {
|
pub fn profile_queries_and_keys(&self) -> bool {
|
||||||
self.opts.debugging_opts.profile_queries_and_keys
|
self.opts.debugging_opts.profile_queries_and_keys
|
||||||
|
@ -454,11 +501,21 @@ impl Session {
|
||||||
pub fn time_llvm_passes(&self) -> bool {
|
pub fn time_llvm_passes(&self) -> bool {
|
||||||
self.opts.debugging_opts.time_llvm_passes
|
self.opts.debugging_opts.time_llvm_passes
|
||||||
}
|
}
|
||||||
pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats }
|
pub fn trans_stats(&self) -> bool {
|
||||||
pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats }
|
self.opts.debugging_opts.trans_stats
|
||||||
pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments }
|
}
|
||||||
pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify }
|
pub fn meta_stats(&self) -> bool {
|
||||||
pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats }
|
self.opts.debugging_opts.meta_stats
|
||||||
|
}
|
||||||
|
pub fn asm_comments(&self) -> bool {
|
||||||
|
self.opts.debugging_opts.asm_comments
|
||||||
|
}
|
||||||
|
pub fn no_verify(&self) -> bool {
|
||||||
|
self.opts.debugging_opts.no_verify
|
||||||
|
}
|
||||||
|
pub fn borrowck_stats(&self) -> bool {
|
||||||
|
self.opts.debugging_opts.borrowck_stats
|
||||||
|
}
|
||||||
pub fn print_llvm_passes(&self) -> bool {
|
pub fn print_llvm_passes(&self) -> bool {
|
||||||
self.opts.debugging_opts.print_llvm_passes
|
self.opts.debugging_opts.print_llvm_passes
|
||||||
}
|
}
|
||||||
|
@ -481,18 +538,11 @@ impl Session {
|
||||||
*(self.features.borrow_mut()) = Some(features);
|
*(self.features.borrow_mut()) = Some(features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If true, we should gather causal information during NLL
|
|
||||||
/// checking. This will eventually be the normal thing, but right
|
|
||||||
/// now it is too unoptimized.
|
|
||||||
pub fn nll_dump_cause(&self) -> bool {
|
|
||||||
self.opts.debugging_opts.nll_dump_cause
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates the flavor of LTO to use for this compilation.
|
/// Calculates the flavor of LTO to use for this compilation.
|
||||||
pub fn lto(&self) -> config::Lto {
|
pub fn lto(&self) -> config::Lto {
|
||||||
// If our target has codegen requirements ignore the command line
|
// If our target has codegen requirements ignore the command line
|
||||||
if self.target.target.options.requires_lto {
|
if self.target.target.options.requires_lto {
|
||||||
return config::Lto::Fat
|
return config::Lto::Fat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user specified something, return that. If they only said `-C
|
// If the user specified something, return that. If they only said `-C
|
||||||
|
@ -500,9 +550,7 @@ impl Session {
|
||||||
// then ensure we can't use a ThinLTO.
|
// then ensure we can't use a ThinLTO.
|
||||||
match self.opts.cg.lto {
|
match self.opts.cg.lto {
|
||||||
config::Lto::No => {}
|
config::Lto::No => {}
|
||||||
config::Lto::Yes if self.opts.cli_forced_thinlto_off => {
|
config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat,
|
||||||
return config::Lto::Fat
|
|
||||||
}
|
|
||||||
other => return other,
|
other => return other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,28 +563,28 @@ impl Session {
|
||||||
// If processing command line options determined that we're incompatible
|
// If processing command line options determined that we're incompatible
|
||||||
// with ThinLTO (e.g. `-C lto --emit llvm-ir`) then return that option.
|
// with ThinLTO (e.g. `-C lto --emit llvm-ir`) then return that option.
|
||||||
if self.opts.cli_forced_thinlto_off {
|
if self.opts.cli_forced_thinlto_off {
|
||||||
return config::Lto::No
|
return config::Lto::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If `-Z thinlto` specified process that, but note that this is mostly
|
// If `-Z thinlto` specified process that, but note that this is mostly
|
||||||
// a deprecated option now that `-C lto=thin` exists.
|
// a deprecated option now that `-C lto=thin` exists.
|
||||||
if let Some(enabled) = self.opts.debugging_opts.thinlto {
|
if let Some(enabled) = self.opts.debugging_opts.thinlto {
|
||||||
if enabled {
|
if enabled {
|
||||||
return config::Lto::ThinLocal
|
return config::Lto::ThinLocal;
|
||||||
} else {
|
} else {
|
||||||
return config::Lto::No
|
return config::Lto::No;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's only one codegen unit and LTO isn't enabled then there's
|
// If there's only one codegen unit and LTO isn't enabled then there's
|
||||||
// no need for ThinLTO so just return false.
|
// no need for ThinLTO so just return false.
|
||||||
if self.codegen_units() == 1 {
|
if self.codegen_units() == 1 {
|
||||||
return config::Lto::No
|
return config::Lto::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right now ThinLTO isn't compatible with incremental compilation.
|
// Right now ThinLTO isn't compatible with incremental compilation.
|
||||||
if self.opts.incremental.is_some() {
|
if self.opts.incremental.is_some() {
|
||||||
return config::Lto::No
|
return config::Lto::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
||||||
|
@ -550,15 +598,23 @@ impl Session {
|
||||||
/// Returns the panic strategy for this compile session. If the user explicitly selected one
|
/// Returns the panic strategy for this compile session. If the user explicitly selected one
|
||||||
/// using '-C panic', use that, otherwise use the panic strategy defined by the target.
|
/// using '-C panic', use that, otherwise use the panic strategy defined by the target.
|
||||||
pub fn panic_strategy(&self) -> PanicStrategy {
|
pub fn panic_strategy(&self) -> PanicStrategy {
|
||||||
self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy)
|
self.opts
|
||||||
|
.cg
|
||||||
|
.panic
|
||||||
|
.unwrap_or(self.target.target.options.panic_strategy)
|
||||||
}
|
}
|
||||||
pub fn linker_flavor(&self) -> LinkerFlavor {
|
pub fn linker_flavor(&self) -> LinkerFlavor {
|
||||||
self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
|
self.opts
|
||||||
|
.debugging_opts
|
||||||
|
.linker_flavor
|
||||||
|
.unwrap_or(self.target.target.linker_flavor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fewer_names(&self) -> bool {
|
pub fn fewer_names(&self) -> bool {
|
||||||
let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) ||
|
let more_names = self.opts
|
||||||
self.opts.output_types.contains_key(&OutputType::Bitcode);
|
.output_types
|
||||||
|
.contains_key(&OutputType::LlvmAssembly)
|
||||||
|
|| self.opts.output_types.contains_key(&OutputType::Bitcode);
|
||||||
self.opts.debugging_opts.fewer_names || !more_names
|
self.opts.debugging_opts.fewer_names || !more_names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +628,9 @@ impl Session {
|
||||||
self.opts.debugging_opts.enable_nonzeroing_move_hints
|
self.opts.debugging_opts.enable_nonzeroing_move_hints
|
||||||
}
|
}
|
||||||
pub fn overflow_checks(&self) -> bool {
|
pub fn overflow_checks(&self) -> bool {
|
||||||
self.opts.cg.overflow_checks
|
self.opts
|
||||||
|
.cg
|
||||||
|
.overflow_checks
|
||||||
.or(self.opts.debugging_opts.force_overflow_checks)
|
.or(self.opts.debugging_opts.force_overflow_checks)
|
||||||
.unwrap_or(self.opts.debug_assertions)
|
.unwrap_or(self.opts.debug_assertions)
|
||||||
}
|
}
|
||||||
|
@ -603,50 +661,59 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
|
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
|
||||||
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
|
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo
|
||||||
!self.target.target.options.eliminate_frame_pointer
|
|| !self.target.target.options.eliminate_frame_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the symbol name for the registrar function,
|
/// Returns the symbol name for the registrar function,
|
||||||
/// given the crate Svh and the function DefIndex.
|
/// given the crate Svh and the function DefIndex.
|
||||||
pub fn generate_plugin_registrar_symbol(&self,
|
pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
|
||||||
disambiguator: CrateDisambiguator)
|
format!(
|
||||||
-> String {
|
"__rustc_plugin_registrar_{}__",
|
||||||
format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
|
disambiguator.to_fingerprint().to_hex()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_derive_registrar_symbol(&self,
|
pub fn generate_derive_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
|
||||||
disambiguator: CrateDisambiguator)
|
format!(
|
||||||
-> String {
|
"__rustc_derive_registrar_{}__",
|
||||||
format!("__rustc_derive_registrar_{}__", disambiguator.to_fingerprint().to_hex())
|
disambiguator.to_fingerprint().to_hex()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
||||||
match self.opts.maybe_sysroot {
|
match self.opts.maybe_sysroot {
|
||||||
Some (ref sysroot) => sysroot,
|
Some(ref sysroot) => sysroot,
|
||||||
None => self.default_sysroot.as_ref()
|
None => self.default_sysroot
|
||||||
.expect("missing sysroot and default_sysroot in Session")
|
.as_ref()
|
||||||
|
.expect("missing sysroot and default_sysroot in Session"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
|
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
|
||||||
filesearch::FileSearch::new(self.sysroot(),
|
filesearch::FileSearch::new(
|
||||||
&self.opts.target_triple,
|
self.sysroot(),
|
||||||
&self.opts.search_paths,
|
&self.opts.target_triple,
|
||||||
kind)
|
&self.opts.search_paths,
|
||||||
|
kind,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
|
pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
|
||||||
filesearch::FileSearch::new(
|
filesearch::FileSearch::new(
|
||||||
self.sysroot(),
|
self.sysroot(),
|
||||||
config::host_triple(),
|
config::host_triple(),
|
||||||
&self.opts.search_paths,
|
&self.opts.search_paths,
|
||||||
kind)
|
kind,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_incr_session_load_dep_graph(&self, load: bool) {
|
pub fn set_incr_session_load_dep_graph(&self, load: bool) {
|
||||||
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
||||||
|
|
||||||
match *incr_comp_session {
|
match *incr_comp_session {
|
||||||
IncrCompSession::Active { ref mut load_dep_graph, .. } => {
|
IncrCompSession::Active {
|
||||||
|
ref mut load_dep_graph,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
*load_dep_graph = load;
|
*load_dep_graph = load;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -661,14 +728,20 @@ impl Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_incr_comp_session(&self,
|
pub fn init_incr_comp_session(
|
||||||
session_dir: PathBuf,
|
&self,
|
||||||
lock_file: flock::Lock,
|
session_dir: PathBuf,
|
||||||
load_dep_graph: bool) {
|
lock_file: flock::Lock,
|
||||||
|
load_dep_graph: bool,
|
||||||
|
) {
|
||||||
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
||||||
|
|
||||||
if let IncrCompSession::NotInitialized = *incr_comp_session { } else {
|
if let IncrCompSession::NotInitialized = *incr_comp_session {
|
||||||
bug!("Trying to initialize IncrCompSession `{:?}`", *incr_comp_session)
|
} else {
|
||||||
|
bug!(
|
||||||
|
"Trying to initialize IncrCompSession `{:?}`",
|
||||||
|
*incr_comp_session
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
*incr_comp_session = IncrCompSession::Active {
|
*incr_comp_session = IncrCompSession::Active {
|
||||||
|
@ -681,8 +754,12 @@ impl Session {
|
||||||
pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) {
|
pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) {
|
||||||
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
||||||
|
|
||||||
if let IncrCompSession::Active { .. } = *incr_comp_session { } else {
|
if let IncrCompSession::Active { .. } = *incr_comp_session {
|
||||||
bug!("Trying to finalize IncrCompSession `{:?}`", *incr_comp_session)
|
} else {
|
||||||
|
bug!(
|
||||||
|
"Trying to finalize IncrCompSession `{:?}`",
|
||||||
|
*incr_comp_session
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: This will also drop the lock file, thus unlocking the directory
|
// Note: This will also drop the lock file, thus unlocking the directory
|
||||||
|
@ -695,35 +772,42 @@ impl Session {
|
||||||
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
||||||
|
|
||||||
let session_directory = match *incr_comp_session {
|
let session_directory = match *incr_comp_session {
|
||||||
IncrCompSession::Active { ref session_directory, .. } => {
|
IncrCompSession::Active {
|
||||||
session_directory.clone()
|
ref session_directory,
|
||||||
}
|
..
|
||||||
|
} => session_directory.clone(),
|
||||||
IncrCompSession::InvalidBecauseOfErrors { .. } => return,
|
IncrCompSession::InvalidBecauseOfErrors { .. } => return,
|
||||||
_ => bug!("Trying to invalidate IncrCompSession `{:?}`",
|
_ => bug!(
|
||||||
*incr_comp_session),
|
"Trying to invalidate IncrCompSession `{:?}`",
|
||||||
|
*incr_comp_session
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: This will also drop the lock file, thus unlocking the directory
|
// Note: This will also drop the lock file, thus unlocking the directory
|
||||||
*incr_comp_session = IncrCompSession::InvalidBecauseOfErrors {
|
*incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory };
|
||||||
session_directory,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn incr_comp_session_dir(&self) -> cell::Ref<PathBuf> {
|
pub fn incr_comp_session_dir(&self) -> cell::Ref<PathBuf> {
|
||||||
let incr_comp_session = self.incr_comp_session.borrow();
|
let incr_comp_session = self.incr_comp_session.borrow();
|
||||||
cell::Ref::map(incr_comp_session, |incr_comp_session| {
|
cell::Ref::map(
|
||||||
match *incr_comp_session {
|
incr_comp_session,
|
||||||
IncrCompSession::NotInitialized => {
|
|incr_comp_session| match *incr_comp_session {
|
||||||
bug!("Trying to get session directory from IncrCompSession `{:?}`",
|
IncrCompSession::NotInitialized => bug!(
|
||||||
*incr_comp_session)
|
"Trying to get session directory from IncrCompSession `{:?}`",
|
||||||
|
*incr_comp_session
|
||||||
|
),
|
||||||
|
IncrCompSession::Active {
|
||||||
|
ref session_directory,
|
||||||
|
..
|
||||||
}
|
}
|
||||||
IncrCompSession::Active { ref session_directory, .. } |
|
| IncrCompSession::Finalized {
|
||||||
IncrCompSession::Finalized { ref session_directory } |
|
ref session_directory,
|
||||||
IncrCompSession::InvalidBecauseOfErrors { ref session_directory } => {
|
|
||||||
session_directory
|
|
||||||
}
|
}
|
||||||
}
|
| IncrCompSession::InvalidBecauseOfErrors {
|
||||||
})
|
ref session_directory,
|
||||||
|
} => session_directory,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<PathBuf>> {
|
pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<PathBuf>> {
|
||||||
|
@ -735,25 +819,39 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_perf_stats(&self) {
|
pub fn print_perf_stats(&self) {
|
||||||
println!("Total time spent computing SVHs: {}",
|
println!(
|
||||||
duration_to_secs_str(self.perf_stats.svh_time.get()));
|
"Total time spent computing SVHs: {}",
|
||||||
println!("Total time spent computing incr. comp. hashes: {}",
|
duration_to_secs_str(self.perf_stats.svh_time.get())
|
||||||
duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get()));
|
);
|
||||||
println!("Total number of incr. comp. hashes computed: {}",
|
println!(
|
||||||
self.perf_stats.incr_comp_hashes_count.get());
|
"Total time spent computing incr. comp. hashes: {}",
|
||||||
println!("Total number of bytes hashed for incr. comp.: {}",
|
duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get())
|
||||||
self.perf_stats.incr_comp_bytes_hashed.get());
|
);
|
||||||
|
println!(
|
||||||
|
"Total number of incr. comp. hashes computed: {}",
|
||||||
|
self.perf_stats.incr_comp_hashes_count.get()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"Total number of bytes hashed for incr. comp.: {}",
|
||||||
|
self.perf_stats.incr_comp_bytes_hashed.get()
|
||||||
|
);
|
||||||
if self.perf_stats.incr_comp_hashes_count.get() != 0 {
|
if self.perf_stats.incr_comp_hashes_count.get() != 0 {
|
||||||
println!("Average bytes hashed per incr. comp. HIR node: {}",
|
println!(
|
||||||
self.perf_stats.incr_comp_bytes_hashed.get() /
|
"Average bytes hashed per incr. comp. HIR node: {}",
|
||||||
self.perf_stats.incr_comp_hashes_count.get());
|
self.perf_stats.incr_comp_bytes_hashed.get()
|
||||||
|
/ self.perf_stats.incr_comp_hashes_count.get()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("Average bytes hashed per incr. comp. HIR node: N/A");
|
println!("Average bytes hashed per incr. comp. HIR node: N/A");
|
||||||
}
|
}
|
||||||
println!("Total time spent computing symbol hashes: {}",
|
println!(
|
||||||
duration_to_secs_str(self.perf_stats.symbol_hash_time.get()));
|
"Total time spent computing symbol hashes: {}",
|
||||||
println!("Total time spent decoding DefPath tables: {}",
|
duration_to_secs_str(self.perf_stats.symbol_hash_time.get())
|
||||||
duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get()));
|
);
|
||||||
|
println!(
|
||||||
|
"Total time spent decoding DefPath tables: {}",
|
||||||
|
duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
|
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
|
||||||
|
@ -768,15 +866,15 @@ impl Session {
|
||||||
println!("optimization-fuel-exhausted: {}", msg());
|
println!("optimization-fuel-exhausted: {}", msg());
|
||||||
self.out_of_fuel.set(true);
|
self.out_of_fuel.set(true);
|
||||||
} else if fuel > 0 {
|
} else if fuel > 0 {
|
||||||
self.optimization_fuel_limit.set(fuel-1);
|
self.optimization_fuel_limit.set(fuel - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match self.print_fuel_crate {
|
match self.print_fuel_crate {
|
||||||
Some(ref c) if c == crate_name=> {
|
Some(ref c) if c == crate_name => {
|
||||||
self.print_fuel.set(self.print_fuel.get()+1);
|
self.print_fuel.set(self.print_fuel.get() + 1);
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
@ -792,10 +890,10 @@ impl Session {
|
||||||
/// compilation
|
/// compilation
|
||||||
pub fn codegen_units(&self) -> usize {
|
pub fn codegen_units(&self) -> usize {
|
||||||
if let Some(n) = self.opts.cli_forced_codegen_units {
|
if let Some(n) = self.opts.cli_forced_codegen_units {
|
||||||
return n
|
return n;
|
||||||
}
|
}
|
||||||
if let Some(n) = self.target.target.options.default_codegen_units {
|
if let Some(n) = self.target.target.options.default_codegen_units {
|
||||||
return n as usize
|
return n as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Why is 16 codegen units the default all the time?
|
// Why is 16 codegen units the default all the time?
|
||||||
|
@ -865,29 +963,34 @@ impl Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_session(sopts: config::Options,
|
pub fn build_session(
|
||||||
local_crate_source_file: Option<PathBuf>,
|
sopts: config::Options,
|
||||||
registry: errors::registry::Registry)
|
local_crate_source_file: Option<PathBuf>,
|
||||||
-> Session {
|
registry: errors::registry::Registry,
|
||||||
|
) -> Session {
|
||||||
let file_path_mapping = sopts.file_path_mapping();
|
let file_path_mapping = sopts.file_path_mapping();
|
||||||
|
|
||||||
build_session_with_codemap(sopts,
|
build_session_with_codemap(
|
||||||
local_crate_source_file,
|
sopts,
|
||||||
registry,
|
local_crate_source_file,
|
||||||
Lrc::new(codemap::CodeMap::new(file_path_mapping)),
|
registry,
|
||||||
None)
|
Lrc::new(codemap::CodeMap::new(file_path_mapping)),
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_session_with_codemap(sopts: config::Options,
|
pub fn build_session_with_codemap(
|
||||||
local_crate_source_file: Option<PathBuf>,
|
sopts: config::Options,
|
||||||
registry: errors::registry::Registry,
|
local_crate_source_file: Option<PathBuf>,
|
||||||
codemap: Lrc<codemap::CodeMap>,
|
registry: errors::registry::Registry,
|
||||||
emitter_dest: Option<Box<dyn Write + Send>>)
|
codemap: Lrc<codemap::CodeMap>,
|
||||||
-> Session {
|
emitter_dest: Option<Box<dyn Write + Send>>,
|
||||||
|
) -> Session {
|
||||||
// FIXME: This is not general enough to make the warning lint completely override
|
// FIXME: This is not general enough to make the warning lint completely override
|
||||||
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
||||||
// later via the source code.
|
// later via the source code.
|
||||||
let warnings_allow = sopts.lint_opts
|
let warnings_allow = sopts
|
||||||
|
.lint_opts
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&&(ref key, _)| *key == "warnings")
|
.filter(|&&(ref key, _)| *key == "warnings")
|
||||||
.map(|&(_, ref level)| *level == lint::Allow)
|
.map(|&(_, ref level)| *level == lint::Allow)
|
||||||
|
@ -901,60 +1004,70 @@ pub fn build_session_with_codemap(sopts: config::Options,
|
||||||
|
|
||||||
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
|
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
|
||||||
|
|
||||||
let emitter: Box<dyn Emitter> = match (sopts.error_format, emitter_dest) {
|
let emitter: Box<dyn Emitter> =
|
||||||
(config::ErrorOutputType::HumanReadable(color_config), None) => {
|
match (sopts.error_format, emitter_dest) {
|
||||||
Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()),
|
(config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
|
||||||
false, sopts.debugging_opts.teach)
|
EmitterWriter::stderr(
|
||||||
.ui_testing(sopts.debugging_opts.ui_testing))
|
color_config,
|
||||||
}
|
Some(codemap.clone()),
|
||||||
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
|
false,
|
||||||
Box::new(EmitterWriter::new(dst, Some(codemap.clone()),
|
sopts.debugging_opts.teach,
|
||||||
false, false)
|
).ui_testing(sopts.debugging_opts.ui_testing),
|
||||||
.ui_testing(sopts.debugging_opts.ui_testing))
|
),
|
||||||
}
|
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
|
||||||
(config::ErrorOutputType::Json(pretty), None) => {
|
EmitterWriter::new(dst, Some(codemap.clone()), false, false)
|
||||||
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(),
|
.ui_testing(sopts.debugging_opts.ui_testing),
|
||||||
pretty, sopts.debugging_opts.approximate_suggestions)
|
),
|
||||||
.ui_testing(sopts.debugging_opts.ui_testing))
|
(config::ErrorOutputType::Json(pretty), None) => Box::new(
|
||||||
}
|
JsonEmitter::stderr(
|
||||||
(config::ErrorOutputType::Json(pretty), Some(dst)) => {
|
Some(registry),
|
||||||
Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(),
|
codemap.clone(),
|
||||||
pretty, sopts.debugging_opts.approximate_suggestions)
|
pretty,
|
||||||
.ui_testing(sopts.debugging_opts.ui_testing))
|
sopts.debugging_opts.approximate_suggestions,
|
||||||
}
|
).ui_testing(sopts.debugging_opts.ui_testing),
|
||||||
(config::ErrorOutputType::Short(color_config), None) => {
|
),
|
||||||
Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false))
|
(config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
|
||||||
}
|
JsonEmitter::new(
|
||||||
(config::ErrorOutputType::Short(_), Some(dst)) => {
|
dst,
|
||||||
Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true, false))
|
Some(registry),
|
||||||
}
|
codemap.clone(),
|
||||||
};
|
pretty,
|
||||||
|
sopts.debugging_opts.approximate_suggestions,
|
||||||
|
).ui_testing(sopts.debugging_opts.ui_testing),
|
||||||
|
),
|
||||||
|
(config::ErrorOutputType::Short(color_config), None) => Box::new(
|
||||||
|
EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false),
|
||||||
|
),
|
||||||
|
(config::ErrorOutputType::Short(_), Some(dst)) => {
|
||||||
|
Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true, false))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let diagnostic_handler =
|
let diagnostic_handler = errors::Handler::with_emitter_and_flags(
|
||||||
errors::Handler::with_emitter_and_flags(
|
emitter,
|
||||||
emitter,
|
errors::HandlerFlags {
|
||||||
errors::HandlerFlags {
|
can_emit_warnings,
|
||||||
can_emit_warnings,
|
treat_err_as_bug,
|
||||||
treat_err_as_bug,
|
external_macro_backtrace,
|
||||||
external_macro_backtrace,
|
..Default::default()
|
||||||
.. Default::default()
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
build_session_(sopts,
|
build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap)
|
||||||
local_crate_source_file,
|
|
||||||
diagnostic_handler,
|
|
||||||
codemap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_session_(sopts: config::Options,
|
pub fn build_session_(
|
||||||
local_crate_source_file: Option<PathBuf>,
|
sopts: config::Options,
|
||||||
span_diagnostic: errors::Handler,
|
local_crate_source_file: Option<PathBuf>,
|
||||||
codemap: Lrc<codemap::CodeMap>)
|
span_diagnostic: errors::Handler,
|
||||||
-> Session {
|
codemap: Lrc<codemap::CodeMap>,
|
||||||
|
) -> Session {
|
||||||
let host = match Target::search(config::host_triple()) {
|
let host = match Target::search(config::host_triple()) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
span_diagnostic.fatal(&format!("Error loading host specification: {}", e)).raise();
|
span_diagnostic
|
||||||
|
.fatal(&format!("Error loading host specification: {}", e))
|
||||||
|
.raise();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
|
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
|
||||||
|
@ -962,26 +1075,25 @@ pub fn build_session_(sopts: config::Options,
|
||||||
let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
|
let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
|
||||||
let default_sysroot = match sopts.maybe_sysroot {
|
let default_sysroot = match sopts.maybe_sysroot {
|
||||||
Some(_) => None,
|
Some(_) => None,
|
||||||
None => Some(filesearch::get_or_default_sysroot())
|
None => Some(filesearch::get_or_default_sysroot()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let file_path_mapping = sopts.file_path_mapping();
|
let file_path_mapping = sopts.file_path_mapping();
|
||||||
|
|
||||||
let local_crate_source_file = local_crate_source_file.map(|path| {
|
let local_crate_source_file =
|
||||||
file_path_mapping.map_prefix(path).0
|
local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
|
||||||
});
|
|
||||||
|
|
||||||
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
|
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
|
||||||
let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref()
|
let optimization_fuel_limit =
|
||||||
.map(|i| i.1).unwrap_or(0));
|
Cell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
|
||||||
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
|
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
|
||||||
let print_fuel = Cell::new(0);
|
let print_fuel = Cell::new(0);
|
||||||
|
|
||||||
let working_dir = match env::current_dir() {
|
let working_dir = match env::current_dir() {
|
||||||
Ok(dir) => dir,
|
Ok(dir) => dir,
|
||||||
Err(e) => {
|
Err(e) => p_s.span_diagnostic
|
||||||
p_s.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e)).raise()
|
.fatal(&format!("Current directory is invalid: {}", e))
|
||||||
}
|
.raise(),
|
||||||
};
|
};
|
||||||
let working_dir = file_path_mapping.map_prefix(working_dir);
|
let working_dir = file_path_mapping.map_prefix(working_dir);
|
||||||
|
|
||||||
|
@ -1090,15 +1202,11 @@ pub enum IncrCompSession {
|
||||||
},
|
},
|
||||||
/// This is the state after the session directory has been finalized. In this
|
/// This is the state after the session directory has been finalized. In this
|
||||||
/// state, the contents of the directory must not be modified any more.
|
/// state, the contents of the directory must not be modified any more.
|
||||||
Finalized {
|
Finalized { session_directory: PathBuf },
|
||||||
session_directory: PathBuf,
|
|
||||||
},
|
|
||||||
/// This is an error state that is reached when some compilation error has
|
/// This is an error state that is reached when some compilation error has
|
||||||
/// occurred. It indicates that the contents of the session directory must
|
/// occurred. It indicates that the contents of the session directory must
|
||||||
/// not be used, since they might be invalid.
|
/// not be used, since they might be invalid.
|
||||||
InvalidBecauseOfErrors {
|
InvalidBecauseOfErrors { session_directory: PathBuf },
|
||||||
session_directory: PathBuf,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
||||||
|
@ -1133,7 +1241,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum CompileIncomplete {
|
pub enum CompileIncomplete {
|
||||||
Stopped,
|
Stopped,
|
||||||
Errored(ErrorReported)
|
Errored(ErrorReported),
|
||||||
}
|
}
|
||||||
impl From<ErrorReported> for CompileIncomplete {
|
impl From<ErrorReported> for CompileIncomplete {
|
||||||
fn from(err: ErrorReported) -> CompileIncomplete {
|
fn from(err: ErrorReported) -> CompileIncomplete {
|
||||||
|
@ -1160,23 +1268,27 @@ pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! {
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn span_bug_fmt<S: Into<MultiSpan>>(file: &'static str,
|
pub fn span_bug_fmt<S: Into<MultiSpan>>(
|
||||||
line: u32,
|
file: &'static str,
|
||||||
span: S,
|
line: u32,
|
||||||
args: fmt::Arguments) -> ! {
|
span: S,
|
||||||
|
args: fmt::Arguments,
|
||||||
|
) -> ! {
|
||||||
opt_span_bug_fmt(file, line, Some(span), args);
|
opt_span_bug_fmt(file, line, Some(span), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opt_span_bug_fmt<S: Into<MultiSpan>>(file: &'static str,
|
fn opt_span_bug_fmt<S: Into<MultiSpan>>(
|
||||||
line: u32,
|
file: &'static str,
|
||||||
span: Option<S>,
|
line: u32,
|
||||||
args: fmt::Arguments) -> ! {
|
span: Option<S>,
|
||||||
|
args: fmt::Arguments,
|
||||||
|
) -> ! {
|
||||||
tls::with_opt(move |tcx| {
|
tls::with_opt(move |tcx| {
|
||||||
let msg = format!("{}:{}: {}", file, line, args);
|
let msg = format!("{}:{}: {}", file, line, args);
|
||||||
match (tcx, span) {
|
match (tcx, span) {
|
||||||
(Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg),
|
(Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg),
|
||||||
(Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
|
(Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
|
||||||
(None, _) => panic!(msg)
|
(None, _) => panic!(msg),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
unreachable!();
|
unreachable!();
|
||||||
|
|
|
@ -124,6 +124,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
(place, span): (&Place<'tcx>, Span),
|
(place, span): (&Place<'tcx>, Span),
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
) {
|
) {
|
||||||
|
let tcx = self.tcx;
|
||||||
let value_msg = match self.describe_place(place) {
|
let value_msg = match self.describe_place(place) {
|
||||||
Some(name) => format!("`{}`", name),
|
Some(name) => format!("`{}`", name),
|
||||||
None => "value".to_owned(),
|
None => "value".to_owned(),
|
||||||
|
@ -132,7 +133,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
Some(name) => format!("`{}`", name),
|
Some(name) => format!("`{}`", name),
|
||||||
None => "value".to_owned(),
|
None => "value".to_owned(),
|
||||||
};
|
};
|
||||||
let mut err = self.tcx.cannot_move_when_borrowed(
|
let mut err = tcx.cannot_move_when_borrowed(
|
||||||
span,
|
span,
|
||||||
&self.describe_place(place).unwrap_or("_".to_owned()),
|
&self.describe_place(place).unwrap_or("_".to_owned()),
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
|
@ -152,7 +153,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
(place, span): (&Place<'tcx>, Span),
|
(place, span): (&Place<'tcx>, Span),
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
) {
|
) {
|
||||||
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
|
let tcx = self.tcx;
|
||||||
|
let mut err = tcx.cannot_use_when_mutably_borrowed(
|
||||||
span,
|
span,
|
||||||
&self.describe_place(place).unwrap_or("_".to_owned()),
|
&self.describe_place(place).unwrap_or("_".to_owned()),
|
||||||
self.retrieve_borrow_span(borrow),
|
self.retrieve_borrow_span(borrow),
|
||||||
|
@ -254,6 +256,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
.unwrap_or(issued_span);
|
.unwrap_or(issued_span);
|
||||||
|
|
||||||
let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
|
let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
|
||||||
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// FIXME: supply non-"" `opt_via` when appropriate
|
// FIXME: supply non-"" `opt_via` when appropriate
|
||||||
let mut err = match (
|
let mut err = match (
|
||||||
|
@ -265,8 +268,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"mutable",
|
"mutable",
|
||||||
) {
|
) {
|
||||||
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
|
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
|
||||||
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
|
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => {
|
||||||
.cannot_reborrow_already_borrowed(
|
tcx.cannot_reborrow_already_borrowed(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
"",
|
||||||
|
@ -277,10 +280,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"",
|
"",
|
||||||
end_issued_loan_span,
|
end_issued_loan_span,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
(BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => self.tcx
|
(BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => {
|
||||||
.cannot_mutably_borrow_multiply(
|
tcx.cannot_mutably_borrow_multiply(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
"",
|
||||||
|
@ -288,18 +292,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"",
|
"",
|
||||||
end_issued_loan_span,
|
end_issued_loan_span,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
(BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => self.tcx
|
(BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => {
|
||||||
.cannot_uniquely_borrow_by_two_closures(
|
tcx.cannot_uniquely_borrow_by_two_closures(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
issued_span,
|
issued_span,
|
||||||
end_issued_loan_span,
|
end_issued_loan_span,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
(BorrowKind::Unique, _, _, _, _, _) => self.tcx.cannot_uniquely_borrow_by_one_closure(
|
(BorrowKind::Unique, _, _, _, _, _) => tcx.cannot_uniquely_borrow_by_one_closure(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
"",
|
||||||
|
@ -310,8 +316,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
),
|
||||||
|
|
||||||
(BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => self.tcx
|
(BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => {
|
||||||
.cannot_reborrow_already_uniquely_borrowed(
|
tcx.cannot_reborrow_already_uniquely_borrowed(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
"",
|
||||||
|
@ -320,10 +326,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"",
|
"",
|
||||||
end_issued_loan_span,
|
end_issued_loan_span,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => self.tcx
|
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => {
|
||||||
.cannot_reborrow_already_uniquely_borrowed(
|
tcx.cannot_reborrow_already_uniquely_borrowed(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
"",
|
||||||
|
@ -332,7 +339,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"",
|
"",
|
||||||
end_issued_loan_span,
|
end_issued_loan_span,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(),
|
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -466,11 +474,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
_proper_span: Span,
|
_proper_span: Span,
|
||||||
end_span: Option<Span>,
|
end_span: Option<Span>,
|
||||||
) {
|
) {
|
||||||
let mut err = self.tcx.path_does_not_live_long_enough(
|
let tcx = self.tcx;
|
||||||
borrow_span,
|
let mut err =
|
||||||
&format!("`{}`", name),
|
tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir);
|
||||||
Origin::Mir,
|
|
||||||
);
|
|
||||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||||
err.span_label(
|
err.span_label(
|
||||||
drop_span,
|
drop_span,
|
||||||
|
@ -493,9 +499,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
proper_span: Span,
|
proper_span: Span,
|
||||||
end_span: Option<Span>,
|
end_span: Option<Span>,
|
||||||
) {
|
) {
|
||||||
|
let tcx = self.tcx;
|
||||||
let mut err =
|
let mut err =
|
||||||
self.tcx
|
tcx.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
||||||
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
|
||||||
err.span_label(proper_span, "temporary value does not live long enough");
|
err.span_label(proper_span, "temporary value does not live long enough");
|
||||||
err.span_label(
|
err.span_label(
|
||||||
drop_span,
|
drop_span,
|
||||||
|
@ -527,16 +533,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
context, name, scope_tree, borrow, drop_span, borrow_span
|
context, name, scope_tree, borrow, drop_span, borrow_span
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut err = self.tcx.path_does_not_live_long_enough(
|
let tcx = self.tcx;
|
||||||
borrow_span,
|
let mut err =
|
||||||
&format!("`{}`", name),
|
tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir);
|
||||||
Origin::Mir,
|
|
||||||
);
|
|
||||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||||
err.span_label(drop_span, "borrowed value only lives until here");
|
err.span_label(drop_span, "borrowed value only lives until here");
|
||||||
|
|
||||||
if !self.tcx.nll() {
|
if !tcx.nll() {
|
||||||
self.tcx.note_and_explain_region(
|
tcx.note_and_explain_region(
|
||||||
scope_tree,
|
scope_tree,
|
||||||
&mut err,
|
&mut err,
|
||||||
"borrowed value must be valid for ",
|
"borrowed value must be valid for ",
|
||||||
|
@ -566,14 +570,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
context, scope_tree, borrow, drop_span, proper_span
|
context, scope_tree, borrow, drop_span, proper_span
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let tcx = self.tcx;
|
||||||
let mut err =
|
let mut err =
|
||||||
self.tcx
|
tcx.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
||||||
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
|
||||||
err.span_label(proper_span, "temporary value does not live long enough");
|
err.span_label(proper_span, "temporary value does not live long enough");
|
||||||
err.span_label(drop_span, "temporary value only lives until here");
|
err.span_label(drop_span, "temporary value only lives until here");
|
||||||
|
|
||||||
if !self.tcx.nll() {
|
if !tcx.nll() {
|
||||||
self.tcx.note_and_explain_region(
|
tcx.note_and_explain_region(
|
||||||
scope_tree,
|
scope_tree,
|
||||||
&mut err,
|
&mut err,
|
||||||
"borrowed value must be valid for ",
|
"borrowed value must be valid for ",
|
||||||
|
@ -592,7 +596,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
(place, span): (&Place<'tcx>, Span),
|
(place, span): (&Place<'tcx>, Span),
|
||||||
loan: &BorrowData<'tcx>,
|
loan: &BorrowData<'tcx>,
|
||||||
) {
|
) {
|
||||||
let mut err = self.tcx.cannot_assign_to_borrowed(
|
let tcx = self.tcx;
|
||||||
|
let mut err = tcx.cannot_assign_to_borrowed(
|
||||||
span,
|
span,
|
||||||
self.retrieve_borrow_span(loan),
|
self.retrieve_borrow_span(loan),
|
||||||
&self.describe_place(place).unwrap_or("_".to_owned()),
|
&self.describe_place(place).unwrap_or("_".to_owned()),
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
||||||
|
|
||||||
use borrow_check::nll::region_infer::RegionInferenceContext;
|
use borrow_check::nll::region_infer::{RegionCausalInfo, RegionInferenceContext};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map::definitions::DefPathData;
|
use rustc::hir::map::definitions::DefPathData;
|
||||||
|
@ -231,6 +231,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
access_place_error_reported: FxHashSet(),
|
access_place_error_reported: FxHashSet(),
|
||||||
reservation_error_reported: FxHashSet(),
|
reservation_error_reported: FxHashSet(),
|
||||||
nonlexical_regioncx: opt_regioncx.clone(),
|
nonlexical_regioncx: opt_regioncx.clone(),
|
||||||
|
nonlexical_cause_info: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let borrows = Borrows::new(tcx, mir, opt_regioncx, def_id, body_id);
|
let borrows = Borrows::new(tcx, mir, opt_regioncx, def_id, body_id);
|
||||||
|
@ -311,6 +312,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||||
/// contains the results from region inference and lets us e.g.
|
/// contains the results from region inference and lets us e.g.
|
||||||
/// find out which CFG points are contained in each borrow region.
|
/// find out which CFG points are contained in each borrow region.
|
||||||
nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
|
nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
|
||||||
|
nonlexical_cause_info: Option<RegionCausalInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that:
|
// Check that:
|
||||||
|
@ -337,9 +339,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"MirBorrowckCtxt::process_statement({:?}, {:?}): {}",
|
"MirBorrowckCtxt::process_statement({:?}, {:?}): {}",
|
||||||
location,
|
location, stmt, flow_state
|
||||||
stmt,
|
|
||||||
flow_state
|
|
||||||
);
|
);
|
||||||
let span = stmt.source_info.span;
|
let span = stmt.source_info.span;
|
||||||
|
|
||||||
|
@ -441,9 +441,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||||
let loc = location;
|
let loc = location;
|
||||||
debug!(
|
debug!(
|
||||||
"MirBorrowckCtxt::process_terminator({:?}, {:?}): {}",
|
"MirBorrowckCtxt::process_terminator({:?}, {:?}): {}",
|
||||||
location,
|
location, term, flow_state
|
||||||
term,
|
|
||||||
flow_state
|
|
||||||
);
|
);
|
||||||
let span = term.source_info.span;
|
let span = term.source_info.span;
|
||||||
|
|
||||||
|
@ -582,8 +580,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||||
TerminatorKind::Goto { target: _ }
|
TerminatorKind::Goto { target: _ }
|
||||||
| TerminatorKind::Abort
|
| TerminatorKind::Abort
|
||||||
| TerminatorKind::Unreachable
|
| TerminatorKind::Unreachable
|
||||||
| TerminatorKind::FalseEdges { real_target: _, imaginary_targets: _ }
|
| TerminatorKind::FalseEdges {
|
||||||
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
|
real_target: _,
|
||||||
|
imaginary_targets: _,
|
||||||
|
}
|
||||||
|
| TerminatorKind::FalseUnwind {
|
||||||
|
real_target: _,
|
||||||
|
unwind: _,
|
||||||
|
} => {
|
||||||
// no data used, thus irrelevant to borrowck
|
// no data used, thus irrelevant to borrowck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,7 +687,8 @@ enum LocalMutationIsAllowed {
|
||||||
|
|
||||||
struct AccessErrorsReported {
|
struct AccessErrorsReported {
|
||||||
mutability_error: bool,
|
mutability_error: bool,
|
||||||
#[allow(dead_code)] conflict_error: bool,
|
#[allow(dead_code)]
|
||||||
|
conflict_error: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -719,9 +724,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
/// allowed to be split into separate Reservation and
|
/// allowed to be split into separate Reservation and
|
||||||
/// Activation phases.
|
/// Activation phases.
|
||||||
fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool {
|
fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool {
|
||||||
self.tcx.two_phase_borrows() &&
|
self.tcx.two_phase_borrows()
|
||||||
(kind.allows_two_phase_borrow() ||
|
&& (kind.allows_two_phase_borrow()
|
||||||
self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
|
|| self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes `access_place` as appropriate for dropping the value
|
/// Invokes `access_place` as appropriate for dropping the value
|
||||||
|
@ -753,16 +758,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let field_ty = gcx.normalize_associated_type_in_env(&field_ty, self.param_env);
|
let field_ty = gcx.normalize_associated_type_in_env(&field_ty, self.param_env);
|
||||||
let place = drop_place.clone().field(Field::new(index), field_ty);
|
let place = drop_place.clone().field(Field::new(index), field_ty);
|
||||||
|
|
||||||
self.visit_terminator_drop(
|
self.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
|
||||||
loc,
|
|
||||||
term,
|
|
||||||
flow_state,
|
|
||||||
&place,
|
|
||||||
field_ty,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// We have now refined the type of the value being
|
// We have now refined the type of the value being
|
||||||
// dropped (potentially) to just the type of a
|
// dropped (potentially) to just the type of a
|
||||||
|
@ -779,7 +777,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
flow_state,
|
flow_state,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,8 +799,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Activation(_, borrow_index) = rw {
|
if let Activation(_, borrow_index) = rw {
|
||||||
if self.reservation_error_reported.contains(&place_span.0) {
|
if self.reservation_error_reported.contains(&place_span.0) {
|
||||||
debug!("skipping access_place for activation of invalid reservation \
|
debug!(
|
||||||
place: {:?} borrow_index: {:?}", place_span.0, borrow_index);
|
"skipping access_place for activation of invalid reservation \
|
||||||
|
place: {:?} borrow_index: {:?}",
|
||||||
|
place_span.0, borrow_index
|
||||||
|
);
|
||||||
return AccessErrorsReported {
|
return AccessErrorsReported {
|
||||||
mutability_error: false,
|
mutability_error: false,
|
||||||
conflict_error: true,
|
conflict_error: true,
|
||||||
|
@ -810,9 +811,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.access_place_error_reported.contains(&(place_span.0.clone(), place_span.1)) {
|
if self.access_place_error_reported
|
||||||
debug!("access_place: suppressing error place_span=`{:?}` kind=`{:?}`",
|
.contains(&(place_span.0.clone(), place_span.1))
|
||||||
place_span, kind);
|
{
|
||||||
|
debug!(
|
||||||
|
"access_place: suppressing error place_span=`{:?}` kind=`{:?}`",
|
||||||
|
place_span, kind
|
||||||
|
);
|
||||||
return AccessErrorsReported {
|
return AccessErrorsReported {
|
||||||
mutability_error: false,
|
mutability_error: false,
|
||||||
conflict_error: true,
|
conflict_error: true,
|
||||||
|
@ -825,9 +830,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
|
self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
|
||||||
|
|
||||||
if conflict_error || mutability_error {
|
if conflict_error || mutability_error {
|
||||||
debug!("access_place: logging error place_span=`{:?}` kind=`{:?}`",
|
debug!(
|
||||||
place_span, kind);
|
"access_place: logging error place_span=`{:?}` kind=`{:?}`",
|
||||||
self.access_place_error_reported.insert((place_span.0.clone(), place_span.1));
|
place_span, kind
|
||||||
|
);
|
||||||
|
self.access_place_error_reported
|
||||||
|
.insert((place_span.0.clone(), place_span.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessErrorsReported {
|
AccessErrorsReported {
|
||||||
|
@ -875,8 +883,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
|
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
|
||||||
// Reading from mere reservations of mutable-borrows is OK.
|
// Reading from mere reservations of mutable-borrows is OK.
|
||||||
if this.allow_two_phase_borrow(borrow.kind) && index.is_reservation()
|
if this.allow_two_phase_borrow(borrow.kind) && index.is_reservation() {
|
||||||
{
|
|
||||||
return Control::Continue;
|
return Control::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,15 +922,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
place_span.0
|
place_span.0
|
||||||
);
|
);
|
||||||
this.reservation_error_reported.insert(place_span.0.clone());
|
this.reservation_error_reported.insert(place_span.0.clone());
|
||||||
},
|
}
|
||||||
Activation(_, activating) => {
|
Activation(_, activating) => {
|
||||||
debug!(
|
debug!(
|
||||||
"observing check_place for activation of \
|
"observing check_place for activation of \
|
||||||
borrow_index: {:?}",
|
borrow_index: {:?}",
|
||||||
activating
|
activating
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
Read(..) | Write(..) => {},
|
Read(..) | Write(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -1210,11 +1217,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
/// Reports an error if this is a borrow of local data.
|
/// Reports an error if this is a borrow of local data.
|
||||||
/// This is called for all Yield statements on movable generators
|
/// This is called for all Yield statements on movable generators
|
||||||
fn check_for_local_borrow(
|
fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) {
|
||||||
&mut self,
|
|
||||||
borrow: &BorrowData<'tcx>,
|
|
||||||
yield_span: Span)
|
|
||||||
{
|
|
||||||
fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
||||||
match place {
|
match place {
|
||||||
Place::Static(..) => false,
|
Place::Static(..) => false,
|
||||||
|
@ -1226,13 +1229,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
ProjectionElem::Deref => false,
|
ProjectionElem::Deref => false,
|
||||||
|
|
||||||
// For interior references and downcasts, find out if the base is local
|
// For interior references and downcasts, find out if the base is local
|
||||||
ProjectionElem::Field(..) |
|
ProjectionElem::Field(..)
|
||||||
ProjectionElem::Index(..) |
|
| ProjectionElem::Index(..)
|
||||||
ProjectionElem::ConstantIndex { .. } |
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
ProjectionElem::Subslice { .. } |
|
| ProjectionElem::Subslice { .. }
|
||||||
ProjectionElem::Downcast(..) => {
|
| ProjectionElem::Downcast(..) => borrow_of_local_data(&proj.base),
|
||||||
borrow_of_local_data(&proj.base)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1241,9 +1242,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
debug!("check_for_local_borrow({:?})", borrow);
|
debug!("check_for_local_borrow({:?})", borrow);
|
||||||
|
|
||||||
if borrow_of_local_data(&borrow.borrowed_place) {
|
if borrow_of_local_data(&borrow.borrowed_place) {
|
||||||
self.tcx.cannot_borrow_across_generator_yield(self.retrieve_borrow_span(borrow),
|
self.tcx
|
||||||
yield_span,
|
.cannot_borrow_across_generator_yield(
|
||||||
Origin::Mir).emit();
|
self.retrieve_borrow_span(borrow),
|
||||||
|
yield_span,
|
||||||
|
Origin::Mir,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1531,9 +1536,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!(
|
debug!(
|
||||||
"check_access_permissions({:?}, {:?}, {:?})",
|
"check_access_permissions({:?}, {:?}, {:?})",
|
||||||
place,
|
place, kind, is_local_mutation_allowed
|
||||||
kind,
|
|
||||||
is_local_mutation_allowed
|
|
||||||
);
|
);
|
||||||
let mut error_reported = false;
|
let mut error_reported = false;
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -1598,8 +1601,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
"Accessing `{:?}` with the kind `{:?}` shouldn't be possible",
|
"Accessing `{:?}` with the kind `{:?}` shouldn't be possible",
|
||||||
place,
|
place, kind
|
||||||
kind
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1699,9 +1701,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let decl = &self.mir.upvar_decls[field.index()];
|
let decl = &self.mir.upvar_decls[field.index()];
|
||||||
debug!(
|
debug!(
|
||||||
"decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
"decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
||||||
decl,
|
decl, is_local_mutation_allowed, place
|
||||||
is_local_mutation_allowed,
|
|
||||||
place
|
|
||||||
);
|
);
|
||||||
match (decl.mutability, is_local_mutation_allowed) {
|
match (decl.mutability, is_local_mutation_allowed) {
|
||||||
(Mutability::Not, LocalMutationIsAllowed::No)
|
(Mutability::Not, LocalMutationIsAllowed::No)
|
||||||
|
@ -1722,7 +1722,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// If this is a field projection, and the field is being projected from a closure type,
|
/// If this is a field projection, and the field is being projected from a closure type,
|
||||||
/// then returns the index of the field being projected. Note that this closure will always
|
/// then returns the index of the field being projected. Note that this closure will always
|
||||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||||
|
@ -1926,9 +1925,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!(
|
debug!(
|
||||||
"places_conflict({:?},{:?},{:?})",
|
"places_conflict({:?},{:?},{:?})",
|
||||||
borrow_place,
|
borrow_place, access_place, access
|
||||||
access_place,
|
|
||||||
access
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Return all the prefixes of `place` in reverse order, including
|
// Return all the prefixes of `place` in reverse order, including
|
||||||
|
@ -1954,8 +1951,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let access_components = place_elements(access_place);
|
let access_components = place_elements(access_place);
|
||||||
debug!(
|
debug!(
|
||||||
"places_conflict: components {:?} / {:?}",
|
"places_conflict: components {:?} / {:?}",
|
||||||
borrow_components,
|
borrow_components, access_components
|
||||||
access_components
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let borrow_components = borrow_components
|
let borrow_components = borrow_components
|
||||||
|
@ -2161,8 +2157,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let borrowed = &data[i.borrow_index()];
|
let borrowed = &data[i.borrow_index()];
|
||||||
|
|
||||||
if self.places_conflict(&borrowed.borrowed_place, place, access) {
|
if self.places_conflict(&borrowed.borrowed_place, place, access) {
|
||||||
debug!("each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
|
debug!(
|
||||||
i, borrowed, place, access);
|
"each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
|
||||||
|
i, borrowed, place, access
|
||||||
|
);
|
||||||
let ctrl = op(self, i, borrowed);
|
let ctrl = op(self, i, borrowed);
|
||||||
if ctrl == Control::Break {
|
if ctrl == Control::Break {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,19 +18,29 @@ use rustc_errors::DiagnosticBuilder;
|
||||||
use util::liveness::{self, DefUse, LivenessMode};
|
use util::liveness::{self, DefUse, LivenessMode};
|
||||||
|
|
||||||
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
/// Adds annotations to `err` explaining *why* the borrow contains the
|
||||||
|
/// point from `context`. This is key for the "3-point errors"
|
||||||
|
/// [described in the NLL RFC][d].
|
||||||
|
///
|
||||||
|
/// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
|
||||||
pub(in borrow_check) fn explain_why_borrow_contains_point(
|
pub(in borrow_check) fn explain_why_borrow_contains_point(
|
||||||
&self,
|
&mut self,
|
||||||
context: Context,
|
context: Context,
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
) {
|
) {
|
||||||
if let Some(regioncx) = &self.nonlexical_regioncx {
|
if let Some(regioncx) = &self.nonlexical_regioncx {
|
||||||
if let Some(cause) = regioncx.why_region_contains_point(borrow.region, context.loc) {
|
let mir = self.mir;
|
||||||
let mir = self.mir;
|
|
||||||
|
|
||||||
|
if self.nonlexical_cause_info.is_none() {
|
||||||
|
self.nonlexical_cause_info = Some(regioncx.compute_causal_info(mir));
|
||||||
|
}
|
||||||
|
|
||||||
|
let cause_info = self.nonlexical_cause_info.as_ref().unwrap();
|
||||||
|
if let Some(cause) = cause_info.why_region_contains_point(borrow.region, context.loc) {
|
||||||
match *cause.root_cause() {
|
match *cause.root_cause() {
|
||||||
Cause::LiveVar(local, location) => {
|
Cause::LiveVar(local, location) => {
|
||||||
match find_regular_use(&mir, regioncx, borrow, location, local) {
|
match find_regular_use(mir, regioncx, borrow, location, local) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
mir.source_info(p).span,
|
mir.source_info(p).span,
|
||||||
|
@ -48,9 +58,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cause::DropVar(local, location) => {
|
Cause::DropVar(local, location) => {
|
||||||
match find_drop_use(&mir, regioncx, borrow, location, local) {
|
match find_drop_use(mir, regioncx, borrow, location, local) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
let local_name = &mir.local_decls[local].name.unwrap();
|
let local_name = mir.local_decls[local].name.unwrap();
|
||||||
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
mir.source_info(p).span,
|
mir.source_info(p).span,
|
||||||
|
|
|
@ -124,6 +124,10 @@ pub(crate) enum Cause {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct RegionCausalInfo {
|
||||||
|
inferred_values: RegionValues,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Constraint {
|
pub struct Constraint {
|
||||||
// NB. The ordering here is not significant for correctness, but
|
// NB. The ordering here is not significant for correctness, but
|
||||||
|
@ -250,16 +254,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
.map(|origin| RegionDefinition::new(origin))
|
.map(|origin| RegionDefinition::new(origin))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let nll_dump_cause = ty::tls::with(|tcx| tcx.sess.nll_dump_cause());
|
|
||||||
|
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
definitions,
|
definitions,
|
||||||
elements: elements.clone(),
|
elements: elements.clone(),
|
||||||
liveness_constraints: RegionValues::new(
|
liveness_constraints: RegionValues::new(elements, num_region_variables),
|
||||||
elements,
|
|
||||||
num_region_variables,
|
|
||||||
TrackCauses(nll_dump_cause),
|
|
||||||
),
|
|
||||||
inferred_values: None,
|
inferred_values: None,
|
||||||
constraints: Vec::new(),
|
constraints: Vec::new(),
|
||||||
type_tests: Vec::new(),
|
type_tests: Vec::new(),
|
||||||
|
@ -348,17 +346,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
inferred_values.contains(r.to_region_vid(), p)
|
inferred_values.contains(r.to_region_vid(), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the *reason* that the region `r` contains the given point.
|
|
||||||
pub(crate) fn why_region_contains_point<R>(&self, r: R, p: Location) -> Option<Rc<Cause>>
|
|
||||||
where
|
|
||||||
R: ToRegionVid,
|
|
||||||
{
|
|
||||||
let inferred_values = self.inferred_values
|
|
||||||
.as_ref()
|
|
||||||
.expect("region values not yet inferred");
|
|
||||||
inferred_values.cause(r.to_region_vid(), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns access to the value of `r` for debugging purposes.
|
/// Returns access to the value of `r` for debugging purposes.
|
||||||
pub(super) fn region_value_str(&self, r: RegionVid) -> String {
|
pub(super) fn region_value_str(&self, r: RegionVid) -> String {
|
||||||
let inferred_values = self.inferred_values
|
let inferred_values = self.inferred_values
|
||||||
|
@ -449,13 +436,25 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-execute the region inference, this time tracking causal information.
|
||||||
|
/// This is significantly slower, so it is done only when an error is being reported.
|
||||||
|
pub(super) fn compute_causal_info(&self, mir: &Mir<'tcx>) -> RegionCausalInfo {
|
||||||
|
let inferred_values = self.compute_region_values(mir, TrackCauses(true));
|
||||||
|
RegionCausalInfo { inferred_values }
|
||||||
|
}
|
||||||
|
|
||||||
/// Propagate the region constraints: this will grow the values
|
/// Propagate the region constraints: this will grow the values
|
||||||
/// for each region variable until all the constraints are
|
/// for each region variable until all the constraints are
|
||||||
/// satisfied. Note that some values may grow **too** large to be
|
/// satisfied. Note that some values may grow **too** large to be
|
||||||
/// feasible, but we check this later.
|
/// feasible, but we check this later.
|
||||||
fn propagate_constraints(&mut self, mir: &Mir<'tcx>) {
|
fn propagate_constraints(&mut self, mir: &Mir<'tcx>) {
|
||||||
debug!("propagate_constraints()");
|
let inferred_values = self.compute_region_values(mir, TrackCauses(false));
|
||||||
debug!("propagate_constraints: constraints={:#?}", {
|
self.inferred_values = Some(inferred_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_region_values(&self, mir: &Mir<'tcx>, track_causes: TrackCauses) -> RegionValues {
|
||||||
|
debug!("compute_region_values()");
|
||||||
|
debug!("compute_region_values: constraints={:#?}", {
|
||||||
let mut constraints: Vec<_> = self.constraints.iter().collect();
|
let mut constraints: Vec<_> = self.constraints.iter().collect();
|
||||||
constraints.sort();
|
constraints.sort();
|
||||||
constraints
|
constraints
|
||||||
|
@ -463,7 +462,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
|
|
||||||
// The initial values for each region are derived from the liveness
|
// The initial values for each region are derived from the liveness
|
||||||
// constraints we have accumulated.
|
// constraints we have accumulated.
|
||||||
let mut inferred_values = self.liveness_constraints.clone();
|
let mut inferred_values = self.liveness_constraints.duplicate(track_causes);
|
||||||
|
|
||||||
let dependency_map = self.build_dependency_map();
|
let dependency_map = self.build_dependency_map();
|
||||||
|
|
||||||
|
@ -507,7 +506,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
debug!("\n");
|
debug!("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inferred_values = Some(inferred_values);
|
inferred_values
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds up a map from each region variable X to a vector with the
|
/// Builds up a map from each region variable X to a vector with the
|
||||||
|
@ -1097,6 +1096,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RegionCausalInfo {
|
||||||
|
/// Returns the *reason* that the region `r` contains the given point.
|
||||||
|
pub(super) fn why_region_contains_point<R>(&self, r: R, p: Location) -> Option<Rc<Cause>>
|
||||||
|
where
|
||||||
|
R: ToRegionVid,
|
||||||
|
{
|
||||||
|
self.inferred_values.cause(r.to_region_vid(), p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> RegionDefinition<'tcx> {
|
impl<'tcx> RegionDefinition<'tcx> {
|
||||||
fn new(origin: RegionVariableOrigin) -> Self {
|
fn new(origin: RegionVariableOrigin) -> Self {
|
||||||
// Create a new region definition. Note that, for free
|
// Create a new region definition. Note that, for free
|
||||||
|
|
|
@ -184,7 +184,6 @@ impl ToElementIndex for RegionElementIndex {
|
||||||
/// compact `SparseBitMatrix` representation, with one row per region
|
/// compact `SparseBitMatrix` representation, with one row per region
|
||||||
/// variable. The columns consist of either universal regions or
|
/// variable. The columns consist of either universal regions or
|
||||||
/// points in the CFG.
|
/// points in the CFG.
|
||||||
#[derive(Clone)]
|
|
||||||
pub(super) struct RegionValues {
|
pub(super) struct RegionValues {
|
||||||
elements: Rc<RegionValueElements>,
|
elements: Rc<RegionValueElements>,
|
||||||
matrix: SparseBitMatrix<RegionVid, RegionElementIndex>,
|
matrix: SparseBitMatrix<RegionVid, RegionElementIndex>,
|
||||||
|
@ -199,11 +198,10 @@ pub(super) struct RegionValues {
|
||||||
type CauseMap = FxHashMap<(RegionVid, RegionElementIndex), Rc<Cause>>;
|
type CauseMap = FxHashMap<(RegionVid, RegionElementIndex), Rc<Cause>>;
|
||||||
|
|
||||||
impl RegionValues {
|
impl RegionValues {
|
||||||
pub(super) fn new(
|
/// Creates a new set of "region values" that tracks causal information.
|
||||||
elements: &Rc<RegionValueElements>,
|
/// Each of the regions in num_region_variables will be initialized with an
|
||||||
num_region_variables: usize,
|
/// empty set of points and no causal information.
|
||||||
track_causes: TrackCauses,
|
pub(super) fn new(elements: &Rc<RegionValueElements>, num_region_variables: usize) -> Self {
|
||||||
) -> Self {
|
|
||||||
assert!(
|
assert!(
|
||||||
elements.num_universal_regions <= num_region_variables,
|
elements.num_universal_regions <= num_region_variables,
|
||||||
"universal regions are a subset of the region variables"
|
"universal regions are a subset of the region variables"
|
||||||
|
@ -215,8 +213,22 @@ impl RegionValues {
|
||||||
RegionVid::new(num_region_variables),
|
RegionVid::new(num_region_variables),
|
||||||
RegionElementIndex::new(elements.num_elements()),
|
RegionElementIndex::new(elements.num_elements()),
|
||||||
),
|
),
|
||||||
|
causes: Some(CauseMap::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Duplicates the region values. If track_causes is false, then the
|
||||||
|
/// resulting value will not track causal information (and any existing
|
||||||
|
/// causal information is dropped). Otherwise, the causal information is
|
||||||
|
/// preserved and maintained. Tracking the causal information makes region
|
||||||
|
/// propagation significantly slower, so we prefer not to do it until an
|
||||||
|
/// error is reported.
|
||||||
|
pub(super) fn duplicate(&self, track_causes: TrackCauses) -> Self {
|
||||||
|
Self {
|
||||||
|
elements: self.elements.clone(),
|
||||||
|
matrix: self.matrix.clone(),
|
||||||
causes: if track_causes.0 {
|
causes: if track_causes.0 {
|
||||||
Some(CauseMap::default())
|
self.causes.clone()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,9 @@ LL | let mref = &mut u.s.a;
|
||||||
...
|
...
|
||||||
LL | let nref = &u.z.c;
|
LL | let nref = &u.z.c;
|
||||||
| ^^^^^^ immutable borrow occurs here
|
| ^^^^^^ immutable borrow occurs here
|
||||||
|
LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
|
||||||
|
LL | println!("{} {}", mref, nref)
|
||||||
|
| ---- borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.s.a` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `u.s.a` as mutable because it is also borrowed as immutable
|
||||||
--> $DIR/issue-45157.rs:39:27
|
--> $DIR/issue-45157.rs:39:27
|
||||||
|
@ -14,7 +17,9 @@ LL | let nref = &u.z.c;
|
||||||
| ------ immutable borrow occurs here
|
| ------ immutable borrow occurs here
|
||||||
LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
|
LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
|
||||||
LL | println!("{} {}", mref, nref)
|
LL | println!("{} {}", mref, nref)
|
||||||
| ^^^^ mutable borrow occurs here
|
| ^^^^ ---- borrow later used here
|
||||||
|
| |
|
||||||
|
| mutable borrow occurs here
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Znll-dump-cause
|
|
||||||
|
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
|
||||||
fn gimme(x: &(u32,)) -> &u32 {
|
fn gimme(x: &(u32,)) -> &u32 {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `v` does not live long enough
|
error[E0597]: `v` does not live long enough
|
||||||
--> $DIR/borrowed-local-error.rs:22:9
|
--> $DIR/borrowed-local-error.rs:20:9
|
||||||
|
|
|
|
||||||
LL | let x = gimme({
|
LL | let x = gimme({
|
||||||
| _____________-
|
| _____________-
|
||||||
|
|
|
@ -10,6 +10,8 @@ LL | | //~^ cannot use `e` because it was mutably borrowed [E0503]
|
||||||
LL | | Xyz::B => println!("b"),
|
LL | | Xyz::B => println!("b"),
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____^ use of borrowed `e`
|
| |_____^ use of borrowed `e`
|
||||||
|
LL | *g = Xyz::B;
|
||||||
|
| ----------- borrow later used here
|
||||||
|
|
||||||
error[E0503]: cannot use `e` because it was mutably borrowed
|
error[E0503]: cannot use `e` because it was mutably borrowed
|
||||||
--> $DIR/borrowed-match-issue-45045.rs:25:9
|
--> $DIR/borrowed-match-issue-45045.rs:25:9
|
||||||
|
@ -19,6 +21,9 @@ LL | let f = &mut e;
|
||||||
...
|
...
|
||||||
LL | Xyz::A => println!("a"),
|
LL | Xyz::A => println!("a"),
|
||||||
| ^^^^^^ use of borrowed `e`
|
| ^^^^^^ use of borrowed `e`
|
||||||
|
...
|
||||||
|
LL | *g = Xyz::B;
|
||||||
|
| ----------- borrow later used here
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ LL | let x = &mut block;
|
||||||
LL | println!("{}", x.current);
|
LL | println!("{}", x.current);
|
||||||
LL | let p: &'a u8 = &*block.current;
|
LL | let p: &'a u8 = &*block.current;
|
||||||
| ^^^^^^^^^^^^^^^ immutable borrow occurs here
|
| ^^^^^^^^^^^^^^^ immutable borrow occurs here
|
||||||
|
LL | //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
|
||||||
|
LL | drop(x);
|
||||||
|
| - borrow later used here
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Znll-dump-cause
|
|
||||||
|
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
|
||||||
fn gimme(x: &(u32,)) -> &u32 {
|
fn gimme(x: &(u32,)) -> &u32 {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: borrowed value does not live long enough
|
error[E0597]: borrowed value does not live long enough
|
||||||
--> $DIR/borrowed-temporary-error.rs:22:10
|
--> $DIR/borrowed-temporary-error.rs:20:10
|
||||||
|
|
|
|
||||||
LL | &(v,)
|
LL | &(v,)
|
||||||
| ^^^^ temporary value does not live long enough
|
| ^^^^ temporary value does not live long enough
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Znll-dump-cause
|
|
||||||
|
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `v` does not live long enough
|
error[E0597]: `v` does not live long enough
|
||||||
--> $DIR/borrowed-universal-error-2.rs:18:5
|
--> $DIR/borrowed-universal-error-2.rs:16:5
|
||||||
|
|
|
|
||||||
LL | &v
|
LL | &v
|
||||||
| ^^ borrowed value does not live long enough
|
| ^^ borrowed value does not live long enough
|
||||||
|
@ -7,8 +7,8 @@ LL | //~^ ERROR `v` does not live long enough [E0597]
|
||||||
LL | }
|
LL | }
|
||||||
| - borrowed value only lives until here
|
| - borrowed value only lives until here
|
||||||
|
|
|
|
||||||
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 16:1...
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 14:1...
|
||||||
--> $DIR/borrowed-universal-error-2.rs:16:1
|
--> $DIR/borrowed-universal-error-2.rs:14:1
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Znll-dump-cause
|
|
||||||
|
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: borrowed value does not live long enough
|
error[E0597]: borrowed value does not live long enough
|
||||||
--> $DIR/borrowed-universal-error.rs:22:12
|
--> $DIR/borrowed-universal-error.rs:20:12
|
||||||
|
|
|
|
||||||
LL | gimme(&(v,))
|
LL | gimme(&(v,))
|
||||||
| ^^^^ temporary value does not live long enough
|
| ^^^^ temporary value does not live long enough
|
||||||
|
@ -7,8 +7,8 @@ LL | //~^ ERROR borrowed value does not live long enough [E0597]
|
||||||
LL | }
|
LL | }
|
||||||
| - temporary value only lives until here
|
| - temporary value only lives until here
|
||||||
|
|
|
|
||||||
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:1...
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 18:1...
|
||||||
--> $DIR/borrowed-universal-error.rs:20:1
|
--> $DIR/borrowed-universal-error.rs:18:1
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags:-Znll-dump-cause
|
|
||||||
|
|
||||||
// Test that a structure which tries to store a pointer to `y` into
|
// Test that a structure which tries to store a pointer to `y` into
|
||||||
// `p` (indirectly) fails to compile.
|
// `p` (indirectly) fails to compile.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `y` does not live long enough
|
error[E0597]: `y` does not live long enough
|
||||||
--> $DIR/capture-ref-in-struct.rs:33:16
|
--> $DIR/capture-ref-in-struct.rs:31:16
|
||||||
|
|
|
|
||||||
LL | y: &y,
|
LL | y: &y,
|
||||||
| ^^ borrowed value does not live long enough
|
| ^^ borrowed value does not live long enough
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// basically checking that the MIR type checker correctly enforces the
|
// basically checking that the MIR type checker correctly enforces the
|
||||||
// closure signature.
|
// closure signature.
|
||||||
|
|
||||||
// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
|
// compile-flags:-Znll -Zborrowck=mir -Zverbose
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
// except that the closure does so via a second closure.
|
// except that the closure does so via a second closure.
|
||||||
|
|
||||||
// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
|
// compile-flags:-Znll -Zborrowck=mir -Zverbose
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// `'b`. This relationship is propagated to the closure creator,
|
// `'b`. This relationship is propagated to the closure creator,
|
||||||
// which reports an error.
|
// which reports an error.
|
||||||
|
|
||||||
// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
|
// compile-flags:-Znll -Zborrowck=mir -Zverbose
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ LL | let cell = Cell::new(&a);
|
||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
| - borrowed value only lives until here
|
| - borrowed value only lives until here
|
||||||
|
|
|
||||||
|
= note: borrowed value must be valid for the static lifetime...
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// because of destructor. (Note that the stderr also identifies this
|
// because of destructor. (Note that the stderr also identifies this
|
||||||
// destructor in the error message.)
|
// destructor in the error message.)
|
||||||
|
|
||||||
// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause
|
// compile-flags:-Znll -Zborrowck=mir
|
||||||
|
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
#![feature(dropck_eyepatch)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// a variety of errors from the older, AST-based machinery (notably
|
// a variety of errors from the older, AST-based machinery (notably
|
||||||
// borrowck), and then we get the NLL error at the end.
|
// borrowck), and then we get the NLL error at the end.
|
||||||
|
|
||||||
// compile-flags:-Znll -Zborrowck=compare -Znll-dump-cause
|
// compile-flags:-Znll -Zborrowck=compare
|
||||||
|
|
||||||
struct Map {
|
struct Map {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ LL | let t = &mut *s; // this borrow should last for the entire function
|
||||||
LL | let x = &t.0;
|
LL | let x = &t.0;
|
||||||
LL | *s = (2,); //~ ERROR cannot assign to `*s`
|
LL | *s = (2,); //~ ERROR cannot assign to `*s`
|
||||||
| ^^^^^^^^^ assignment to borrowed `*s` occurs here
|
| ^^^^^^^^^ assignment to borrowed `*s` occurs here
|
||||||
|
LL | *x
|
||||||
|
| -- borrow later used here
|
||||||
|
|
||||||
error[E0621]: explicit lifetime required in the type of `s`
|
error[E0621]: explicit lifetime required in the type of `s`
|
||||||
--> $DIR/guarantor-issue-46974.rs:25:5
|
--> $DIR/guarantor-issue-46974.rs:25:5
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll -Znll-dump-cause
|
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
|
||||||
|
|
||||||
|
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
|
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
|
||||||
|
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
|
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
|
||||||
|
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
|
//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll
|
||||||
|
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
error[E0597]: borrowed value does not live long enough
|
error[E0597]: borrowed value does not live long enough
|
||||||
--> $DIR/return-ref-mut-issue-46557.rs:17:21
|
--> $DIR/return-ref-mut-issue-46557.rs:17:21
|
||||||
|
|
|
|
||||||
LL | let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
|
LL | fn gimme_static_mut() -> &'static mut u32 {
|
||||||
| ^^^^^^^ temporary value does not live long enough
|
| ___________________________________________-
|
||||||
LL | x
|
LL | | let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
|
||||||
LL | }
|
| | ^^^^^^^ temporary value does not live long enough
|
||||||
| - temporary value only lives until here
|
LL | | x
|
||||||
|
LL | | }
|
||||||
|
| | -
|
||||||
|
| | |
|
||||||
|
| |_temporary value only lives until here
|
||||||
|
| borrow later used here
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue