Auto merge of #89019 - Manishearth:rollup-5qp8a5s, r=Manishearth
Rollup of 10 pull requests Successful merges: - #88292 (Enable --generate-link-to-definition for rustc's docs) - #88729 (Recover from `Foo(a: 1, b: 2)`) - #88875 (cleanup(rustc_trait_selection): remove vestigial code from rustc_on_unimplemented) - #88892 (Move object safety suggestions to the end of the error) - #88928 (Document the closure arguments for `reduce`.) - #88976 (Clean up and add doc comments for CStr) - #88983 (Allow calling `get_body_with_borrowck_facts` without `-Z polonius`) - #88985 (Update clobber_abi list to include k[1-7] regs) - #88986 (Update the backtrace crate) - #89009 (Fix typo in `break` docs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e4828d5b7f
49 changed files with 210 additions and 106 deletions
|
@ -14,7 +14,9 @@ pub use super::{
|
|||
};
|
||||
|
||||
/// This function computes Polonius facts for the given body. It makes a copy of
|
||||
/// the body because it needs to regenerate the region identifiers.
|
||||
/// the body because it needs to regenerate the region identifiers. This function
|
||||
/// should never be invoked during a typical compilation session due to performance
|
||||
/// issues with Polonius.
|
||||
///
|
||||
/// Note:
|
||||
/// * This function will panic if the required body was already stolen. This
|
||||
|
@ -22,8 +24,6 @@ pub use super::{
|
|||
/// because they are evaluated during typechecking. The panic can be avoided
|
||||
/// by overriding the `mir_borrowck` query. You can find a complete example
|
||||
/// that shows how to do this at `src/test/run-make/obtain-borrowck/`.
|
||||
/// * This function will also panic if computation of Polonius facts
|
||||
/// (`-Zpolonius` flag) is not enabled.
|
||||
///
|
||||
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
|
||||
pub fn get_body_with_borrowck_facts<'tcx>(
|
||||
|
|
|
@ -154,11 +154,6 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
|
||||
debug!("do_mir_borrowck(def = {:?})", def);
|
||||
|
||||
assert!(
|
||||
!return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius,
|
||||
"borrowck facts can be requested only when Polonius is enabled"
|
||||
);
|
||||
|
||||
let tcx = infcx.tcx;
|
||||
let param_env = tcx.param_env(def.did);
|
||||
let id = tcx.hir().local_def_id_to_hir_id(def.did);
|
||||
|
@ -235,6 +230,8 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
let borrow_set =
|
||||
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
|
||||
|
||||
let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius;
|
||||
|
||||
// Compute non-lexical lifetimes.
|
||||
let nll::NllOutput {
|
||||
regioncx,
|
||||
|
@ -254,6 +251,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
&mdpe.move_data,
|
||||
&borrow_set,
|
||||
&upvars,
|
||||
use_polonius,
|
||||
);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This let us
|
||||
|
|
|
@ -164,8 +164,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
upvars: &[Upvar<'tcx>],
|
||||
use_polonius: bool,
|
||||
) -> NllOutput<'tcx> {
|
||||
let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
|
||||
let mut all_facts =
|
||||
(use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
|
||||
|
||||
let universal_regions = Rc::new(universal_regions);
|
||||
|
||||
|
@ -281,7 +283,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
all_facts.write_to_dir(dir_path, location_table).unwrap();
|
||||
}
|
||||
|
||||
if infcx.tcx.sess.opts.debugging_opts.polonius {
|
||||
if use_polonius {
|
||||
let algorithm =
|
||||
env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
|
||||
let algorithm = Algorithm::from_str(&algorithm).unwrap();
|
||||
|
|
|
@ -72,7 +72,7 @@ pub(super) fn parse(
|
|||
// this with just `span.edition()`. A
|
||||
// `SyntaxContext::root()` from the current crate will
|
||||
// have the edition of the current crate, and a
|
||||
// `SyntaxxContext::root()` from a foreign crate will
|
||||
// `SyntaxContext::root()` from a foreign crate will
|
||||
// have the edition of that crate (which we manually
|
||||
// retrieve via the `edition` parameter).
|
||||
if span.ctxt() == SyntaxContext::root() {
|
||||
|
|
|
@ -83,10 +83,6 @@ pub fn report_object_safety_error(
|
|||
messages.push(msg.clone());
|
||||
}
|
||||
}
|
||||
if trait_span.is_some() {
|
||||
// Only provide the help if its a local trait, otherwise it's not actionable.
|
||||
violation.solution(&mut err);
|
||||
}
|
||||
}
|
||||
}
|
||||
let has_multi_span = !multi_span.is_empty();
|
||||
|
@ -104,5 +100,13 @@ pub fn report_object_safety_error(
|
|||
to be resolvable dynamically; for more information visit \
|
||||
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
||||
);
|
||||
if trait_span.is_some() {
|
||||
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
|
||||
reported_violations.sort();
|
||||
for violation in reported_violations {
|
||||
// Only provide the help if its a local trait, otherwise it's not actionable.
|
||||
violation.solution(&mut err);
|
||||
}
|
||||
}
|
||||
err
|
||||
}
|
||||
|
|
|
@ -730,7 +730,7 @@ pub struct ImplSourceTraitAliasData<'tcx, N> {
|
|||
pub nested: Vec<N>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
||||
pub enum ObjectSafetyViolation {
|
||||
/// `Self: Sized` declared on the trait.
|
||||
SizedSelf(SmallVec<[Span; 1]>),
|
||||
|
@ -879,7 +879,7 @@ impl ObjectSafetyViolation {
|
|||
}
|
||||
|
||||
/// Reasons a method might not be object-safe.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
||||
pub enum MethodViolationCode {
|
||||
/// e.g., `fn foo()`
|
||||
StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
|
||||
|
|
|
@ -28,8 +28,8 @@ pub use self::drop_flag_effects::{
|
|||
on_lookup_result_bits,
|
||||
};
|
||||
pub use self::framework::{
|
||||
fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, Forward,
|
||||
GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
|
||||
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
|
||||
Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
|
||||
ResultsVisitable, ResultsVisitor,
|
||||
};
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ mod unreachable_prop;
|
|||
use rustc_const_eval::transform::check_consts;
|
||||
use rustc_const_eval::transform::promote_consts;
|
||||
use rustc_const_eval::transform::validate;
|
||||
use rustc_const_eval::transform::MirPass;
|
||||
pub use rustc_const_eval::transform::MirPass;
|
||||
use rustc_mir_dataflow::rustc_peek;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
|
@ -907,6 +907,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn look_ahead_type_ascription_as_field(&mut self) -> bool {
|
||||
self.look_ahead(1, |t| t.is_ident())
|
||||
&& self.look_ahead(2, |t| t == &token::Colon)
|
||||
&& self.look_ahead(3, |t| t.can_begin_expr())
|
||||
}
|
||||
|
||||
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
match self.token.uninterpolate().kind {
|
||||
token::Ident(..) => self.parse_dot_suffix(base, lo),
|
||||
|
@ -1056,12 +1062,76 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parse a function call expression, `expr(...)`.
|
||||
fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
|
||||
let seq = self.parse_paren_expr_seq().map(|args| {
|
||||
let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
|
||||
&& self.look_ahead_type_ascription_as_field()
|
||||
{
|
||||
Some((self.clone(), fun.kind.clone()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let open_paren = self.token.span;
|
||||
|
||||
let mut seq = self.parse_paren_expr_seq().map(|args| {
|
||||
self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new())
|
||||
});
|
||||
if let Some(expr) =
|
||||
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
self.recover_seq_parse_error(token::Paren, lo, seq)
|
||||
}
|
||||
|
||||
/// If we encounter a parser state that looks like the user has written a `struct` literal with
|
||||
/// parentheses instead of braces, recover the parser state and provide suggestions.
|
||||
fn maybe_recover_struct_lit_bad_delims(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
open_paren: Span,
|
||||
seq: &mut PResult<'a, P<Expr>>,
|
||||
snapshot: Option<(Self, ExprKind)>,
|
||||
) -> Option<P<Expr>> {
|
||||
match (seq.as_mut(), snapshot) {
|
||||
(Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
|
||||
let name = pprust::path_to_string(&path);
|
||||
snapshot.bump(); // `(`
|
||||
match snapshot.parse_struct_fields(path.clone(), false, token::Paren) {
|
||||
Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
|
||||
// We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
|
||||
// `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
|
||||
*self = snapshot;
|
||||
let close_paren = self.prev_token.span;
|
||||
let span = lo.to(self.prev_token.span);
|
||||
err.cancel();
|
||||
self.struct_span_err(
|
||||
span,
|
||||
"invalid `struct` delimiters or `fn` call arguments",
|
||||
)
|
||||
.multipart_suggestion(
|
||||
&format!("if `{}` is a struct, use braces as delimiters", name),
|
||||
vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.multipart_suggestion(
|
||||
&format!("if `{}` is a function, use the arguments directly", name),
|
||||
fields
|
||||
.into_iter()
|
||||
.map(|field| (field.span.until(field.expr.span), String::new()))
|
||||
.collect(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
return Some(self.mk_expr_err(span));
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(mut err) => err.emit(),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Parse an indexing expression `expr[...]`.
|
||||
fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
self.bump(); // `[`
|
||||
|
@ -2374,14 +2444,12 @@ impl<'a> Parser<'a> {
|
|||
.emit();
|
||||
}
|
||||
|
||||
/// Precondition: already parsed the '{'.
|
||||
pub(super) fn parse_struct_expr(
|
||||
pub(super) fn parse_struct_fields(
|
||||
&mut self,
|
||||
qself: Option<ast::QSelf>,
|
||||
pth: ast::Path,
|
||||
attrs: AttrVec,
|
||||
recover: bool,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
close_delim: token::DelimToken,
|
||||
) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
|
||||
let mut fields = Vec::new();
|
||||
let mut base = ast::StructRest::None;
|
||||
let mut recover_async = false;
|
||||
|
@ -2393,11 +2461,11 @@ impl<'a> Parser<'a> {
|
|||
e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
|
||||
};
|
||||
|
||||
while self.token != token::CloseDelim(token::Brace) {
|
||||
while self.token != token::CloseDelim(close_delim) {
|
||||
if self.eat(&token::DotDot) {
|
||||
let exp_span = self.prev_token.span;
|
||||
// We permit `.. }` on the left-hand side of a destructuring assignment.
|
||||
if self.check(&token::CloseDelim(token::Brace)) {
|
||||
if self.check(&token::CloseDelim(close_delim)) {
|
||||
self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span);
|
||||
base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi());
|
||||
break;
|
||||
|
@ -2438,7 +2506,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) {
|
||||
match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
|
||||
Ok(_) => {
|
||||
if let Some(f) = parsed_field.or(recovery_field) {
|
||||
// Only include the field if there's no parse error for the field name.
|
||||
|
@ -2469,8 +2537,21 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok((fields, base, recover_async))
|
||||
}
|
||||
|
||||
let span = pth.span.to(self.token.span);
|
||||
/// Precondition: already parsed the '{'.
|
||||
pub(super) fn parse_struct_expr(
|
||||
&mut self,
|
||||
qself: Option<ast::QSelf>,
|
||||
pth: ast::Path,
|
||||
attrs: AttrVec,
|
||||
recover: bool,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let lo = pth.span;
|
||||
let (fields, base, recover_async) =
|
||||
self.parse_struct_fields(pth.clone(), recover, token::Brace)?;
|
||||
let span = lo.to(self.token.span);
|
||||
self.expect(&token::CloseDelim(token::Brace))?;
|
||||
let expr = if recover_async {
|
||||
ExprKind::Err
|
||||
|
|
|
@ -934,7 +934,6 @@ symbols! {
|
|||
panic_unwind,
|
||||
panicking,
|
||||
param_attrs,
|
||||
parent_trait,
|
||||
partial_cmp,
|
||||
partial_ord,
|
||||
passes,
|
||||
|
|
|
@ -154,9 +154,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
flags.push((sym::from_method, Some(method.to_string())));
|
||||
}
|
||||
}
|
||||
if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
|
||||
flags.push((sym::parent_trait, Some(t)));
|
||||
}
|
||||
|
||||
if let Some(k) = obligation.cause.span.desugaring_kind() {
|
||||
flags.push((sym::from_desugaring, None));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue