Skip to content

Rollup of 7 pull requests #107104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,16 +1100,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
replace_span: self.ending_semi_or_hi(item.span),
extern_block_suggestion: match sig.header.ext {
Extern::None => None,
Extern::Implicit(start_span) => Some(ExternBlockSuggestion {
Extern::Implicit(start_span) => Some(ExternBlockSuggestion::Implicit {
start_span,
end_span: item.span.shrink_to_hi(),
abi: None,
}),
Extern::Explicit(abi, start_span) => Some(ExternBlockSuggestion {
start_span,
end_span: item.span.shrink_to_hi(),
abi: Some(abi.symbol_unescaped),
}),
Extern::Explicit(abi, start_span) => {
Some(ExternBlockSuggestion::Explicit {
start_span,
end_span: item.span.shrink_to_hi(),
abi: abi.symbol_unescaped,
})
}
},
});
}
Expand Down
42 changes: 17 additions & 25 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Errors emitted by ast_passes.

use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};

Expand Down Expand Up @@ -207,28 +206,21 @@ pub struct FnWithoutBody {
pub extern_block_suggestion: Option<ExternBlockSuggestion>,
}

pub struct ExternBlockSuggestion {
pub start_span: Span,
pub end_span: Span,
pub abi: Option<Symbol>,
}

impl AddToDiagnostic for ExternBlockSuggestion {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi)
} else {
"extern {".to_owned()
};
let end_suggestion = " }".to_owned();

diag.multipart_suggestion(
fluent::extern_block_suggestion,
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
Applicability::MaybeIncorrect,
);
}
#[derive(Subdiagnostic)]
pub enum ExternBlockSuggestion {
#[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")]
Implicit {
#[suggestion_part(code = "extern {{")]
start_span: Span,
#[suggestion_part(code = " }}")]
end_span: Span,
},
#[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")]
Explicit {
#[suggestion_part(code = "extern \"{abi}\" {{")]
start_span: Span,
#[suggestion_part(code = " }}")]
end_span: Span,
abi: Symbol,
},
}
3 changes: 2 additions & 1 deletion compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,5 @@ ast_passes_ty_alias_without_body =
ast_passes_fn_without_body =
free function without a body
.suggestion = provide a definition for the function
.extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block

ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
let mut reinit = None;
match expr.kind {
ExprKind::Assign(lhs, rhs, _) => {
self.visit_expr(lhs);
self.visit_expr(rhs);
self.visit_expr(lhs);

reinit = Some(lhs);
}
Expand Down Expand Up @@ -433,7 +433,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
self.drop_ranges.add_control_edge(self.expr_index, *target)
}),

ExprKind::Break(destination, ..) => {
ExprKind::Break(destination, value) => {
// destination either points to an expression or to a block. We use
// find_target_expression_from_destination to use the last expression of the block
// if destination points to a block.
Expand All @@ -443,7 +443,11 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
// will refer to the end of the block due to the post order traversal.
self.find_target_expression_from_destination(destination).map_or((), |target| {
self.drop_ranges.add_control_edge_hir_id(self.expr_index, target)
})
});

if let Some(value) = value {
self.visit_expr(value);
}
}

ExprKind::Call(f, args) => {
Expand All @@ -465,6 +469,12 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {

ExprKind::AddrOf(..)
| ExprKind::Array(..)
// FIXME(eholk): We probably need special handling for AssignOps. The ScopeTree builder
// in region.rs runs both lhs then rhs and rhs then lhs and then sets all yields to be
// the latest they show up in either traversal. With the older scope-based
// approximation, this was fine, but it's probably not right now. What we probably want
// to do instead is still run both orders, but consider anything that showed up as a
// yield in either order.
| ExprKind::AssignOp(..)
| ExprKind::Binary(..)
| ExprKind::Block(..)
Expand Down Expand Up @@ -502,6 +512,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {

// Increment expr_count here to match what InteriorVisitor expects.
self.expr_index = self.expr_index + 1;

// Save a node mapping to get better CFG visualization
self.drop_ranges.add_node_mapping(pat.hir_id, self.expr_index);
}
}

Expand All @@ -521,7 +534,7 @@ impl DropRangesBuilder {
}
});
}
debug!("hir_id_map: {:?}", tracked_value_map);
debug!("hir_id_map: {:#?}", tracked_value_map);
let num_values = tracked_value_map.len();
Self {
tracked_value_map,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! flow graph when needed for debugging.

use rustc_graphviz as dot;
use rustc_hir::{Expr, ExprKind, Node};
use rustc_middle::ty::TyCtxt;

use super::{DropRangesBuilder, PostOrderId};
Expand Down Expand Up @@ -80,10 +81,14 @@ impl<'a> dot::Labeller<'a> for DropRangesGraph<'_, '_> {
.post_order_map
.iter()
.find(|(_hir_id, &post_order_id)| post_order_id == *n)
.map_or("<unknown>".into(), |(hir_id, _)| self
.tcx
.hir()
.node_to_string(*hir_id))
.map_or("<unknown>".into(), |(hir_id, _)| format!(
"{}{}",
self.tcx.hir().node_to_string(*hir_id),
match self.tcx.hir().find(*hir_id) {
Some(Node::Expr(Expr { kind: ExprKind::Yield(..), .. })) => " (yield)",
_ => "",
}
))
)
.into(),
)
Expand Down
18 changes: 14 additions & 4 deletions compiler/rustc_hir_typeck/src/generator_interior/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
yield_data.expr_and_pat_count, self.expr_count, source_span
);

if self.fcx.sess().opts.unstable_opts.drop_tracking
&& self
.drop_ranges
.is_dropped_at(hir_id, yield_data.expr_and_pat_count)
if self
.is_dropped_at_yield_location(hir_id, yield_data.expr_and_pat_count)
{
debug!("value is dropped at yield point; not recording");
return false;
Expand Down Expand Up @@ -173,6 +171,18 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
}
}
}

/// If drop tracking is enabled, consult drop_ranges to see if a value is
/// known to be dropped at a yield point and therefore can be omitted from
/// the generator witness.
fn is_dropped_at_yield_location(&self, value_hir_id: HirId, yield_location: usize) -> bool {
// short-circuit if drop tracking is not enabled.
if !self.fcx.sess().opts.unstable_opts.drop_tracking {
return false;
}

self.drop_ranges.is_dropped_at(value_hir_id, yield_location)
}
}

pub fn resolve_interior<'a, 'tcx>(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ pub trait PrettyPrinter<'tcx>:
match self.tcx().trimmed_def_paths(()).get(&def_id) {
None => Ok((self, false)),
Some(symbol) => {
self.write_str(symbol.as_str())?;
write!(self, "{}", Ident::with_dummy_span(*symbol))?;
Ok((self, true))
}
}
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,16 @@ impl<'a> Parser<'a> {
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
next_token.kind
{
if self.token.span.hi() == next_token.span.lo() {
// If this integer looks like a float, then recover as such.
//
// We will never encounter the exponent part of a floating
// point literal here, since there's no use of the exponent
// syntax that also constitutes a valid integer, so we need
// not check for that.
if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64)
&& symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
&& self.token.span.hi() == next_token.span.lo()
{
let s = String::from("0.") + symbol.as_str();
let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
return Some(Token::new(kind, self.token.span.to(next_token.span)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
expected_trait_ref,
obligation.cause.code(),
found_node,
obligation.param_env,
)
} else {
let (closure_span, closure_arg_span, found) = found_did
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ pub trait TypeErrCtxtExt<'tcx> {
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
found_node: Option<Node<'_>>,
param_env: ty::ParamEnv<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;

fn note_conflicting_closure_bounds(
Expand Down Expand Up @@ -1978,6 +1979,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
found_node: Option<Node<'_>>,
param_env: ty::ParamEnv<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_ty<'tcx>(
infcx: &InferCtxt<'tcx>,
Expand Down Expand Up @@ -2040,7 +2042,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.note_conflicting_closure_bounds(cause, &mut err);

if let Some(found_node) = found_node {
hint_missing_borrow(span, found, expected, found_node, &mut err);
hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
}

err
Expand Down Expand Up @@ -3747,6 +3749,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {

/// Add a hint to add a missing borrow or remove an unnecessary one.
fn hint_missing_borrow<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
found: Ty<'tcx>,
expected: Ty<'tcx>,
Expand All @@ -3769,7 +3773,7 @@ fn hint_missing_borrow<'tcx>(
// This could be a variant constructor, for example.
let Some(fn_decl) = found_node.fn_decl() else { return; };

let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
let args = fn_decl.inputs.iter().map(|ty| ty);

fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
let mut refs = 0;
Expand All @@ -3785,29 +3789,42 @@ fn hint_missing_borrow<'tcx>(
let mut to_borrow = Vec::new();
let mut remove_borrow = Vec::new();

for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);

if found_ty == expected_ty {
if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
if found_refs < expected_refs {
to_borrow.push((arg_span, expected_arg.to_string()));
to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
} else if found_refs > expected_refs {
remove_borrow.push((arg_span, expected_arg.to_string()));
let mut span = arg.span.shrink_to_lo();
let mut left = found_refs - expected_refs;
let mut ty = arg;
while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
span = span.with_hi(mut_ty.ty.span.lo());
ty = mut_ty.ty;
left -= 1;
}
let sugg = if left == 0 {
(span, String::new())
} else {
(arg.span, expected_arg.to_string())
};
remove_borrow.push(sugg);
}
}
}

if !to_borrow.is_empty() {
err.multipart_suggestion(
err.multipart_suggestion_verbose(
"consider borrowing the argument",
to_borrow,
Applicability::MaybeIncorrect,
);
}

if !remove_borrow.is_empty() {
err.multipart_suggestion(
err.multipart_suggestion_verbose(
"do not borrow the argument",
remove_borrow,
Applicability::MaybeIncorrect,
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/suggestions/recover-invalid-float-invalid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Check that suggestions to add a zero to integers with a preceding dot only appear when the change
// will result in a valid floating point literal.

fn main() {}

fn a() {
_ = .3u32;
//~^ ERROR expected expression, found `.`
}

fn b() {
_ = .0b0;
//~^ ERROR expected expression, found `.`
}

fn c() {
_ = .0o07;
//~^ ERROR expected expression, found `.`
}

fn d() {
_ = .0x0ABC;
//~^ ERROR expected expression, found `.`
}
26 changes: 26 additions & 0 deletions src/test/ui/suggestions/recover-invalid-float-invalid.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: expected expression, found `.`
--> $DIR/recover-invalid-float-invalid.rs:7:9
|
LL | _ = .3u32;
| ^ expected expression

error: expected expression, found `.`
--> $DIR/recover-invalid-float-invalid.rs:12:9
|
LL | _ = .0b0;
| ^ expected expression

error: expected expression, found `.`
--> $DIR/recover-invalid-float-invalid.rs:17:9
|
LL | _ = .0o07;
| ^ expected expression

error: expected expression, found `.`
--> $DIR/recover-invalid-float-invalid.rs:22:9
|
LL | _ = .0x0ABC;
| ^ expected expression

error: aborting due to 4 previous errors

2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/instant_subtraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ declare_clippy_lint! {
/// [`Instant::now()`]: std::time::Instant::now;
#[clippy::version = "1.65.0"]
pub UNCHECKED_DURATION_SUBTRACTION,
suspicious,
pedantic,
"finds unchecked subtraction of a 'Duration' from an 'Instant'"
}

Expand Down
Loading