Skip to content

Commit 739d68a

Browse files
committed
Auto merge of rust-lang#106193 - compiler-errors:rollup-0l54wka, r=compiler-errors
Rollup of 9 pull requests Successful merges: - rust-lang#103718 (More inference-friendly API for lazy) - rust-lang#105765 (Detect likely `.` -> `..` typo in method calls) - rust-lang#105852 (Suggest rewriting a malformed hex literal if we expect a float) - rust-lang#105965 (Provide local extern function arg names) - rust-lang#106064 (Partially fix `explicit_outlives_requirements` lint in macros) - rust-lang#106179 (Fix a formatting error in Iterator::for_each docs) - rust-lang#106181 (Fix doc comment parsing description in book) - rust-lang#106187 (Update the documentation of `Vec` to use `extend(array)` instead of `extend(array.iter().copied())`) - rust-lang#106189 (Fix UnsafeCell Documentation Spelling Error) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 92c1937 + 49d4346 commit 739d68a

File tree

25 files changed

+781
-108
lines changed

25 files changed

+781
-108
lines changed

compiler/rustc_ast_lowering/src/item.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13161316
param.id,
13171317
&param.kind,
13181318
&param.bounds,
1319+
param.colon_span,
1320+
generics.span,
13191321
itctx,
13201322
PredicateOrigin::GenericParam,
13211323
)
@@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13651367
id: NodeId,
13661368
kind: &GenericParamKind,
13671369
bounds: &[GenericBound],
1370+
colon_span: Option<Span>,
1371+
parent_span: Span,
13681372
itctx: &ImplTraitContext,
13691373
origin: PredicateOrigin,
13701374
) -> Option<hir::WherePredicate<'hir>> {
@@ -1377,21 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
13771381

13781382
let ident = self.lower_ident(ident);
13791383
let param_span = ident.span;
1380-
let span = bounds
1381-
.iter()
1382-
.fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| {
1383-
let bound_span = bound.span();
1384-
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
1385-
// as we use this method to get a span appropriate for suggestions.
1386-
if !bound_span.can_be_used_for_suggestions() {
1387-
None
1388-
} else if let Some(span) = span {
1389-
Some(span.to(bound_span))
1390-
} else {
1391-
Some(bound_span)
1392-
}
1393-
})
1394-
.unwrap_or(param_span.shrink_to_hi());
1384+
1385+
// Reconstruct the span of the entire predicate from the individual generic bounds.
1386+
let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
1387+
let span = bounds.iter().fold(span_start, |span_accum, bound| {
1388+
match bound.span().find_ancestor_inside(parent_span) {
1389+
Some(bound_span) => span_accum.to(bound_span),
1390+
None => span_accum,
1391+
}
1392+
});
1393+
let span = self.lower_span(span);
1394+
13951395
match kind {
13961396
GenericParamKind::Const { .. } => None,
13971397
GenericParamKind::Type { .. } => {

compiler/rustc_ast_lowering/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2245,14 +2245,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22452245
) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) {
22462246
// Add a definition for the in-band `Param`.
22472247
let def_id = self.local_def_id(node_id);
2248+
let span = self.lower_span(span);
22482249

22492250
// Set the name to `impl Bound1 + Bound2`.
22502251
let param = hir::GenericParam {
22512252
hir_id: self.lower_node_id(node_id),
22522253
def_id,
22532254
name: ParamName::Plain(self.lower_ident(ident)),
22542255
pure_wrt_drop: false,
2255-
span: self.lower_span(span),
2256+
span,
22562257
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
22572258
colon_span: None,
22582259
};
@@ -2262,6 +2263,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22622263
node_id,
22632264
&GenericParamKind::Type { default: None },
22642265
bounds,
2266+
/* colon_span */ None,
2267+
span,
22652268
&ImplTraitContext::Universal,
22662269
hir::PredicateOrigin::ImplTrait,
22672270
);
@@ -2271,7 +2274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22712274
let ty = hir::TyKind::Path(hir::QPath::Resolved(
22722275
None,
22732276
self.arena.alloc(hir::Path {
2274-
span: self.lower_span(span),
2277+
span,
22752278
res,
22762279
segments:
22772280
arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],

compiler/rustc_hir_typeck/src/demand.rs

+66
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7474
self.note_type_is_not_clone(err, expected, expr_ty, expr);
7575
self.note_need_for_fn_pointer(err, expected, expr_ty);
7676
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
77+
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
7778
}
7879

7980
/// Requires that the two types unify, and prints an error message if
@@ -1607,4 +1608,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16071608
_ => false,
16081609
}
16091610
}
1611+
1612+
/// Identify when the user has written `foo..bar()` instead of `foo.bar()`.
1613+
pub fn check_for_range_as_method_call(
1614+
&self,
1615+
err: &mut Diagnostic,
1616+
expr: &hir::Expr<'_>,
1617+
checked_ty: Ty<'tcx>,
1618+
expected_ty: Ty<'tcx>,
1619+
) {
1620+
if !hir::is_range_literal(expr) {
1621+
return;
1622+
}
1623+
let hir::ExprKind::Struct(
1624+
hir::QPath::LangItem(LangItem::Range, ..),
1625+
[start, end],
1626+
_,
1627+
) = expr.kind else { return; };
1628+
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
1629+
if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
1630+
// Ignore `Foo { field: a..Default::default() }`
1631+
return;
1632+
}
1633+
let mut expr = end.expr;
1634+
while let hir::ExprKind::MethodCall(_, rcvr, ..) = expr.kind {
1635+
// Getting to the root receiver and asserting it is a fn call let's us ignore cases in
1636+
// `src/test/ui/methods/issues/issue-90315.stderr`.
1637+
expr = rcvr;
1638+
}
1639+
let hir::ExprKind::Call(method_name, _) = expr.kind else { return; };
1640+
let ty::Adt(adt, _) = checked_ty.kind() else { return; };
1641+
if self.tcx.lang_items().range_struct() != Some(adt.did()) {
1642+
return;
1643+
}
1644+
if let ty::Adt(adt, _) = expected_ty.kind()
1645+
&& self.tcx.lang_items().range_struct() == Some(adt.did())
1646+
{
1647+
return;
1648+
}
1649+
// Check if start has method named end.
1650+
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; };
1651+
let [hir::PathSegment { ident, .. }] = p.segments else { return; };
1652+
let self_ty = self.typeck_results.borrow().expr_ty(start.expr);
1653+
let Ok(_pick) = self.probe_for_name(
1654+
probe::Mode::MethodCall,
1655+
*ident,
1656+
probe::IsSuggestion(true),
1657+
self_ty,
1658+
expr.hir_id,
1659+
probe::ProbeScope::AllTraits,
1660+
) else { return; };
1661+
let mut sugg = ".";
1662+
let mut span = start.expr.span.between(end.expr.span);
1663+
if span.lo() + BytePos(2) == span.hi() {
1664+
// There's no space between the start, the range op and the end, suggest removal which
1665+
// will be more noticeable than the replacement of `..` with `.`.
1666+
span = span.with_lo(span.lo() + BytePos(1));
1667+
sugg = "";
1668+
}
1669+
err.span_suggestion_verbose(
1670+
span,
1671+
"you likely meant to write a method call instead of a range",
1672+
sugg,
1673+
Applicability::MachineApplicable,
1674+
);
1675+
}
16101676
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+26
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_middle::ty::{
1919
TypeVisitable,
2020
};
2121
use rustc_session::errors::ExprParenthesesNeeded;
22+
use rustc_span::source_map::Spanned;
2223
use rustc_span::symbol::{sym, Ident};
2324
use rustc_span::{Span, Symbol};
2425
use rustc_trait_selection::infer::InferCtxtExt;
@@ -1259,6 +1260,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12591260
);
12601261
true
12611262
}
1263+
ExprKind::Lit(Spanned {
1264+
node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
1265+
span,
1266+
}) => {
1267+
let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; };
1268+
if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
1269+
return false;
1270+
}
1271+
if snippet.len() <= 5 || !snippet.is_char_boundary(snippet.len() - 3) {
1272+
return false;
1273+
}
1274+
let (_, suffix) = snippet.split_at(snippet.len() - 3);
1275+
let value = match suffix {
1276+
"f32" => (lit - 0xf32) / (16 * 16 * 16),
1277+
"f64" => (lit - 0xf64) / (16 * 16 * 16),
1278+
_ => return false,
1279+
};
1280+
err.span_suggestions(
1281+
expr.span,
1282+
"rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float",
1283+
[format!("0x{value:X} as {suffix}"), format!("{value}_{suffix}")],
1284+
Applicability::MaybeIncorrect,
1285+
);
1286+
true
1287+
}
12621288
_ => false,
12631289
}
12641290
}

0 commit comments

Comments
 (0)