Skip to content

Commit 739d68a

Browse files
committedDec 27, 2022
Auto merge of #106193 - compiler-errors:rollup-0l54wka, r=compiler-errors
Rollup of 9 pull requests Successful merges: - #103718 (More inference-friendly API for lazy) - #105765 (Detect likely `.` -> `..` typo in method calls) - #105852 (Suggest rewriting a malformed hex literal if we expect a float) - #105965 (Provide local extern function arg names) - #106064 (Partially fix `explicit_outlives_requirements` lint in macros) - #106179 (Fix a formatting error in Iterator::for_each docs) - #106181 (Fix doc comment parsing description in book) - #106187 (Update the documentation of `Vec` to use `extend(array)` instead of `extend(array.iter().copied())`) - #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

Lines changed: 15 additions & 15 deletions
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

Lines changed: 5 additions & 2 deletions
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

Lines changed: 66 additions & 0 deletions
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

Lines changed: 26 additions & 0 deletions
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
}

‎compiler/rustc_lint/src/builtin.rs

Lines changed: 85 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,30 +2184,36 @@ impl ExplicitOutlivesRequirements {
21842184
tcx: TyCtxt<'tcx>,
21852185
bounds: &hir::GenericBounds<'_>,
21862186
inferred_outlives: &[ty::Region<'tcx>],
2187+
predicate_span: Span,
21872188
) -> Vec<(usize, Span)> {
21882189
use rustc_middle::middle::resolve_lifetime::Region;
21892190

21902191
bounds
21912192
.iter()
21922193
.enumerate()
21932194
.filter_map(|(i, bound)| {
2194-
if let hir::GenericBound::Outlives(lifetime) = bound {
2195-
let is_inferred = match tcx.named_region(lifetime.hir_id) {
2196-
Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| {
2197-
if let ty::ReEarlyBound(ebr) = **r {
2198-
ebr.def_id == def_id
2199-
} else {
2200-
false
2201-
}
2202-
}),
2203-
_ => false,
2204-
};
2205-
is_inferred.then_some((i, bound.span()))
2206-
} else {
2207-
None
2195+
let hir::GenericBound::Outlives(lifetime) = bound else {
2196+
return None;
2197+
};
2198+
2199+
let is_inferred = match tcx.named_region(lifetime.hir_id) {
2200+
Some(Region::EarlyBound(def_id)) => inferred_outlives
2201+
.iter()
2202+
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
2203+
_ => false,
2204+
};
2205+
2206+
if !is_inferred {
2207+
return None;
22082208
}
2209+
2210+
let span = bound.span().find_ancestor_inside(predicate_span)?;
2211+
if in_external_macro(tcx.sess, span) {
2212+
return None;
2213+
}
2214+
2215+
Some((i, span))
22092216
})
2210-
.filter(|(_, span)| !in_external_macro(tcx.sess, *span))
22112217
.collect()
22122218
}
22132219

@@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22732279
use rustc_middle::middle::resolve_lifetime::Region;
22742280

22752281
let def_id = item.owner_id.def_id;
2276-
if let hir::ItemKind::Struct(_, ref hir_generics)
2277-
| hir::ItemKind::Enum(_, ref hir_generics)
2278-
| hir::ItemKind::Union(_, ref hir_generics) = item.kind
2282+
if let hir::ItemKind::Struct(_, hir_generics)
2283+
| hir::ItemKind::Enum(_, hir_generics)
2284+
| hir::ItemKind::Union(_, hir_generics) = item.kind
22792285
{
22802286
let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
22812287
if inferred_outlives.is_empty() {
@@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22902296
let mut dropped_predicate_count = 0;
22912297
let num_predicates = hir_generics.predicates.len();
22922298
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
2293-
let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
2294-
hir::WherePredicate::RegionPredicate(predicate) => {
2295-
if let Some(Region::EarlyBound(region_def_id)) =
2296-
cx.tcx.named_region(predicate.lifetime.hir_id)
2297-
{
2298-
(
2299-
Self::lifetimes_outliving_lifetime(
2300-
inferred_outlives,
2301-
region_def_id,
2302-
),
2303-
&predicate.bounds,
2304-
predicate.span,
2305-
predicate.in_where_clause,
2306-
)
2307-
} else {
2308-
continue;
2309-
}
2310-
}
2311-
hir::WherePredicate::BoundPredicate(predicate) => {
2312-
// FIXME we can also infer bounds on associated types,
2313-
// and should check for them here.
2314-
match predicate.bounded_ty.kind {
2315-
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2316-
let Res::Def(DefKind::TyParam, def_id) = path.res else {
2317-
continue
2318-
};
2319-
let index = ty_generics.param_def_id_to_index[&def_id];
2299+
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
2300+
match where_predicate {
2301+
hir::WherePredicate::RegionPredicate(predicate) => {
2302+
if let Some(Region::EarlyBound(region_def_id)) =
2303+
cx.tcx.named_region(predicate.lifetime.hir_id)
2304+
{
23202305
(
2321-
Self::lifetimes_outliving_type(inferred_outlives, index),
2306+
Self::lifetimes_outliving_lifetime(
2307+
inferred_outlives,
2308+
region_def_id,
2309+
),
23222310
&predicate.bounds,
23232311
predicate.span,
2324-
predicate.origin == PredicateOrigin::WhereClause,
2312+
predicate.in_where_clause,
23252313
)
2326-
}
2327-
_ => {
2314+
} else {
23282315
continue;
23292316
}
23302317
}
2331-
}
2332-
_ => continue,
2333-
};
2318+
hir::WherePredicate::BoundPredicate(predicate) => {
2319+
// FIXME we can also infer bounds on associated types,
2320+
// and should check for them here.
2321+
match predicate.bounded_ty.kind {
2322+
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2323+
let Res::Def(DefKind::TyParam, def_id) = path.res else {
2324+
continue;
2325+
};
2326+
let index = ty_generics.param_def_id_to_index[&def_id];
2327+
(
2328+
Self::lifetimes_outliving_type(inferred_outlives, index),
2329+
&predicate.bounds,
2330+
predicate.span,
2331+
predicate.origin == PredicateOrigin::WhereClause,
2332+
)
2333+
}
2334+
_ => {
2335+
continue;
2336+
}
2337+
}
2338+
}
2339+
_ => continue,
2340+
};
23342341
if relevant_lifetimes.is_empty() {
23352342
continue;
23362343
}
23372344

2338-
let bound_spans =
2339-
self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes);
2345+
let bound_spans = self.collect_outlives_bound_spans(
2346+
cx.tcx,
2347+
bounds,
2348+
&relevant_lifetimes,
2349+
predicate_span,
2350+
);
23402351
bound_count += bound_spans.len();
23412352

23422353
let drop_predicate = bound_spans.len() == bounds.len();
@@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23452356
}
23462357

23472358
if drop_predicate && !in_where_clause {
2348-
lint_spans.push(span);
2359+
lint_spans.push(predicate_span);
23492360
} else if drop_predicate && i + 1 < num_predicates {
23502361
// If all the bounds on a predicate were inferable and there are
23512362
// further predicates, we want to eat the trailing comma.
23522363
let next_predicate_span = hir_generics.predicates[i + 1].span();
2353-
where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo()));
2364+
where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo()));
23542365
} else {
23552366
where_lint_spans.extend(self.consolidate_outlives_bound_spans(
2356-
span.shrink_to_lo(),
2367+
predicate_span.shrink_to_lo(),
23572368
bounds,
23582369
bound_spans,
23592370
));
@@ -2374,24 +2385,35 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23742385
} else {
23752386
hir_generics.span.shrink_to_hi().to(where_span)
23762387
};
2377-
lint_spans.push(full_where_span);
2388+
2389+
// Due to macro expansions, the `full_where_span` might not actually contain all predicates.
2390+
if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) {
2391+
lint_spans.push(full_where_span);
2392+
} else {
2393+
lint_spans.extend(where_lint_spans);
2394+
}
23782395
} else {
23792396
lint_spans.extend(where_lint_spans);
23802397
}
23812398

23822399
if !lint_spans.is_empty() {
2400+
// Do not automatically delete outlives requirements from macros.
2401+
let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions())
2402+
{
2403+
Applicability::MachineApplicable
2404+
} else {
2405+
Applicability::MaybeIncorrect
2406+
};
2407+
23832408
cx.struct_span_lint(
23842409
EXPLICIT_OUTLIVES_REQUIREMENTS,
23852410
lint_spans.clone(),
23862411
fluent::lint_builtin_explicit_outlives,
23872412
|lint| {
23882413
lint.set_arg("count", bound_count).multipart_suggestion(
23892414
fluent::suggestion,
2390-
lint_spans
2391-
.into_iter()
2392-
.map(|span| (span, String::new()))
2393-
.collect::<Vec<_>>(),
2394-
Applicability::MachineApplicable,
2415+
lint_spans.into_iter().map(|span| (span, String::new())).collect(),
2416+
applicability,
23952417
)
23962418
},
23972419
);

‎compiler/rustc_middle/src/hir/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,13 @@ pub fn provide(providers: &mut Providers) {
160160
} else if let Node::TraitItem(&TraitItem {
161161
kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
162162
..
163+
})
164+
| Node::ForeignItem(&ForeignItem {
165+
kind: ForeignItemKind::Fn(_, idents, _),
166+
..
163167
}) = hir.get(hir_id)
164168
{
165-
tcx.arena.alloc_slice(idents)
169+
idents
166170
} else {
167171
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
168172
}

‎compiler/rustc_resolve/src/late.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
1616
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
1717
use rustc_ast::*;
1818
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
19-
use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
19+
use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
2020
use rustc_hir::def::Namespace::{self, *};
2121
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
2222
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> {
536536
in_assignment: Option<&'ast Expr>,
537537
is_assign_rhs: bool,
538538

539+
/// Used to detect possible `.` -> `..` typo when calling methods.
540+
in_range: Option<(&'ast Expr, &'ast Expr)>,
541+
539542
/// If we are currently in a trait object definition. Used to point at the bounds when
540543
/// encountering a struct or enum.
541544
current_trait_object: Option<&'ast [ast::GenericBound]>,
@@ -3320,17 +3323,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33203323
);
33213324
}
33223325

3326+
#[instrument(level = "debug", skip(self))]
33233327
fn smart_resolve_path_fragment(
33243328
&mut self,
33253329
qself: &Option<P<QSelf>>,
33263330
path: &[Segment],
33273331
source: PathSource<'ast>,
33283332
finalize: Finalize,
33293333
) -> PartialRes {
3330-
debug!(
3331-
"smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})",
3332-
qself, path, finalize,
3333-
);
33343334
let ns = source.namespace();
33353335

33363336
let Finalize { node_id, path_span, .. } = finalize;
@@ -3341,8 +3341,28 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33413341

33423342
let def_id = this.parent_scope.module.nearest_parent_mod();
33433343
let instead = res.is_some();
3344-
let suggestion =
3345-
if res.is_none() { this.report_missing_type_error(path) } else { None };
3344+
let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range
3345+
&& path[0].ident.span.lo() == end.span.lo()
3346+
{
3347+
let mut sugg = ".";
3348+
let mut span = start.span.between(end.span);
3349+
if span.lo() + BytePos(2) == span.hi() {
3350+
// There's no space between the start, the range op and the end, suggest
3351+
// removal which will look better.
3352+
span = span.with_lo(span.lo() + BytePos(1));
3353+
sugg = "";
3354+
}
3355+
Some((
3356+
span,
3357+
"you might have meant to write `.` instead of `..`",
3358+
sugg.to_string(),
3359+
Applicability::MaybeIncorrect,
3360+
))
3361+
} else if res.is_none() {
3362+
this.report_missing_type_error(path)
3363+
} else {
3364+
None
3365+
};
33463366

33473367
this.r.use_injections.push(UseError {
33483368
err,
@@ -4005,6 +4025,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
40054025
self.visit_expr(rhs);
40064026
self.diagnostic_metadata.is_assign_rhs = false;
40074027
}
4028+
ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
4029+
self.diagnostic_metadata.in_range = Some((start, end));
4030+
self.resolve_expr(start, Some(expr));
4031+
self.resolve_expr(end, Some(expr));
4032+
self.diagnostic_metadata.in_range = None;
4033+
}
40084034
_ => {
40094035
visit::walk_expr(self, expr);
40104036
}

‎compiler/rustc_span/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ impl Span {
796796

797797
/// Returns a `Span` that would enclose both `self` and `end`.
798798
///
799+
/// Note that this can also be used to extend the span "backwards":
800+
/// `start.to(end)` and `end.to(start)` return the same `Span`.
801+
///
799802
/// ```text
800803
/// ____ ___
801804
/// self lorem ipsum end

‎library/alloc/src/vec/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ mod spec_extend;
166166
/// vec[0] = 7;
167167
/// assert_eq!(vec[0], 7);
168168
///
169-
/// vec.extend([1, 2, 3].iter().copied());
169+
/// vec.extend([1, 2, 3]);
170170
///
171171
/// for x in &vec {
172172
/// println!("{x}");

‎library/core/src/cell.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
17831783
/// until the reference expires. As a special exception, given an `&T`, any part of it that is
17841784
/// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the
17851785
/// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part
1786-
/// of what a reference points to, this means the memory an `&T` points to can be deallocted only if
1786+
/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if
17871787
/// *every part of it* (including padding) is inside an `UnsafeCell`.
17881788
///
17891789
/// However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to

‎library/core/src/cell/lazy.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct LazyCell<T, F = fn() -> T> {
3535
init: Cell<Option<F>>,
3636
}
3737

38-
impl<T, F> LazyCell<T, F> {
38+
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
3939
/// Creates a new lazy value with the given initializing function.
4040
///
4141
/// # Examples
@@ -55,9 +55,7 @@ impl<T, F> LazyCell<T, F> {
5555
pub const fn new(init: F) -> LazyCell<T, F> {
5656
LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
5757
}
58-
}
5958

60-
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
6159
/// Forces the evaluation of this lazy value and returns a reference to
6260
/// the result.
6361
///

‎library/core/src/iter/traits/iterator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ pub trait Iterator {
803803
/// (0..5).map(|x| x * 2 + 1)
804804
/// .for_each(move |x| tx.send(x).unwrap());
805805
///
806-
/// let v: Vec<_> = rx.iter().collect();
806+
/// let v: Vec<_> = rx.iter().collect();
807807
/// assert_eq!(v, vec![1, 3, 5, 7, 9]);
808808
/// ```
809809
///

‎library/core/tests/lazy.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ fn lazy_new() {
106106
assert_eq!(called.get(), 1);
107107
}
108108

109+
// Check that we can infer `T` from closure's type.
110+
#[test]
111+
fn lazy_type_inference() {
112+
let _ = LazyCell::new(|| ());
113+
}
114+
109115
#[test]
110116
fn aliasing_in_get() {
111117
let x = OnceCell::new();

‎library/std/src/sync/lazy_lock.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,14 @@ pub struct LazyLock<T, F = fn() -> T> {
4646
cell: OnceLock<T>,
4747
init: Cell<Option<F>>,
4848
}
49-
50-
impl<T, F> LazyLock<T, F> {
49+
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
5150
/// Creates a new lazy value with the given initializing
5251
/// function.
5352
#[unstable(feature = "once_cell", issue = "74465")]
5453
pub const fn new(f: F) -> LazyLock<T, F> {
5554
LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) }
5655
}
57-
}
5856

59-
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
6057
/// Forces the evaluation of this lazy value and
6158
/// returns a reference to result. This is equivalent
6259
/// to the `Deref` impl, but is explicit.

‎library/std/src/sync/lazy_lock/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ fn sync_lazy_poisoning() {
136136
}
137137
}
138138

139+
// Check that we can infer `T` from closure's type.
140+
#[test]
141+
fn lazy_type_inference() {
142+
let _ = LazyCell::new(|| ());
143+
}
144+
139145
#[test]
140146
fn is_sync_send() {
141147
fn assert_traits<T: Send + Sync>() {}

‎src/doc/rustdoc/src/write-documentation/the-doc-attribute.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ are the same:
99

1010
```rust,no_run
1111
/// This is a doc comment.
12-
#[doc = " This is a doc comment."]
12+
#[doc = r" This is a doc comment."]
1313
# fn f() {}
1414
```
1515

16-
(Note the leading space in the attribute version.)
16+
(Note the leading space and the raw string literal in the attribute version.)
1717

1818
In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is
1919
when generating documentation in macros; the `collapse-docs` pass will combine multiple
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extern "Rust" {
2+
fn dstfn(src: i32, dst: err);
3+
//~^ ERROR cannot find type `err` in this scope
4+
}
5+
6+
fn main() {
7+
dstfn(1);
8+
//~^ ERROR this function takes 2 arguments but 1 argument was supplied
9+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0412]: cannot find type `err` in this scope
2+
--> $DIR/extern-fn-arg-names.rs:2:29
3+
|
4+
LL | fn dstfn(src: i32, dst: err);
5+
| ^^^ not found in this scope
6+
7+
error[E0061]: this function takes 2 arguments but 1 argument was supplied
8+
--> $DIR/extern-fn-arg-names.rs:7:5
9+
|
10+
LL | dstfn(1);
11+
| ^^^^^--- an argument is missing
12+
|
13+
note: function defined here
14+
--> $DIR/extern-fn-arg-names.rs:2:8
15+
|
16+
LL | fn dstfn(src: i32, dst: err);
17+
| ^^^^^
18+
help: provide the argument
19+
|
20+
LL | dstfn(1, /* dst */);
21+
| ~~~~~~~~~~~~~~
22+
23+
error: aborting due to 2 previous errors
24+
25+
Some errors have detailed explanations: E0061, E0412.
26+
For more information about an error, try `rustc --explain E0061`.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// edition:2018
2+
// aux-build:edition-lint-infer-outlives-macro.rs
3+
// run-rustfix
4+
5+
#![deny(explicit_outlives_requirements)]
6+
#![allow(dead_code)]
7+
8+
#[macro_use]
9+
extern crate edition_lint_infer_outlives_macro;
10+
11+
// Test that the lint does not fire if the predicate is from the local crate,
12+
// but all the bounds are from an external macro.
13+
macro_rules! make_foo {
14+
($a:tt) => {
15+
struct Foo<$a, 'b: $a> {
16+
foo: &$a &'b (),
17+
}
18+
19+
struct FooWhere<$a, 'b> where 'b: $a {
20+
foo: &$a &'b (),
21+
}
22+
}
23+
}
24+
25+
gimme_a! {make_foo!}
26+
27+
struct Bar<'a, 'b> {
28+
//~^ ERROR: outlives requirements can be inferred
29+
bar: &'a &'b (),
30+
}
31+
32+
struct BarWhere<'a, 'b> {
33+
//~^ ERROR: outlives requirements can be inferred
34+
bar: &'a &'b (),
35+
}
36+
37+
// Test that the lint *does* fire if the predicate is contained in a local macro.
38+
mod everything_inside {
39+
macro_rules! m {
40+
('b: 'a) => {
41+
struct Foo<'a, 'b>(&'a &'b ());
42+
//~^ ERROR: outlives requirements can be inferred
43+
struct Bar<'a, 'b>(&'a &'b ()) ;
44+
//~^ ERROR: outlives requirements can be inferred
45+
struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ;
46+
//~^ ERROR: outlives requirements can be inferred
47+
};
48+
}
49+
m!('b: 'a);
50+
}
51+
52+
mod inner_lifetime_outside_colon_inside {
53+
macro_rules! m {
54+
($b:lifetime: 'a) => {
55+
struct Foo<'a, $b>(&'a &$b ());
56+
//~^ ERROR: outlives requirements can be inferred
57+
struct Bar<'a, $b>(&'a &$b ()) ;
58+
//~^ ERROR: outlives requirements can be inferred
59+
struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ;
60+
//~^ ERROR: outlives requirements can be inferred
61+
}
62+
}
63+
m!('b: 'a);
64+
}
65+
66+
mod outer_lifetime_outside_colon_inside {
67+
macro_rules! m {
68+
('b: $a:lifetime) => {
69+
struct Foo<$a, 'b: $a>(&$a &'b ());
70+
struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a;
71+
struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a;
72+
}
73+
}
74+
m!('b: 'a);
75+
}
76+
77+
mod both_lifetimes_outside_colon_inside {
78+
macro_rules! m {
79+
($b:lifetime: $a:lifetime) => {
80+
struct Foo<$a, $b: $a>(&$a &$b ());
81+
struct Bar<$a, $b>(&$a &$b ()) where $b: $a;
82+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a;
83+
}
84+
}
85+
m!('b: 'a);
86+
}
87+
88+
mod everything_outside {
89+
macro_rules! m {
90+
($b:lifetime $colon:tt $a:lifetime) => {
91+
struct Foo<$a, $b $colon $a>(&$a &$b ());
92+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
93+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
94+
}
95+
}
96+
m!('b: 'a);
97+
}
98+
99+
mod everything_outside_with_tt_inner {
100+
macro_rules! m {
101+
($b:tt $colon:tt $a:lifetime) => {
102+
struct Foo<$a, $b $colon $a>(&$a &$b ());
103+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
104+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
105+
}
106+
}
107+
m!('b: 'a);
108+
}
109+
110+
// FIXME: These should be consistent.
111+
mod everything_outside_with_tt_outer {
112+
macro_rules! m {
113+
($b:lifetime $colon:tt $a:tt) => {
114+
struct Foo<$a, $b >(&$a &$b ());
115+
//~^ ERROR: outlives requirements can be inferred
116+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
117+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
118+
}
119+
}
120+
m!('b: 'a);
121+
}
122+
123+
mod everything_outside_with_tt_both {
124+
macro_rules! m {
125+
($b:tt $colon:tt $a:tt) => {
126+
struct Foo<$a, $b >(&$a &$b ());
127+
//~^ ERROR: outlives requirements can be inferred
128+
struct Bar<$a, $b>(&$a &$b ()) where ;
129+
//~^ ERROR: outlives requirements can be inferred
130+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ;
131+
//~^ ERROR: outlives requirements can be inferred
132+
}
133+
}
134+
m!('b: 'a);
135+
}
136+
137+
fn main() {}
Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
// edition:2018
22
// aux-build:edition-lint-infer-outlives-macro.rs
3-
4-
// Test that the lint does not fire if the where predicate
5-
// is from the local crate, but all the bounds are from an
6-
// external macro.
3+
// run-rustfix
74

85
#![deny(explicit_outlives_requirements)]
6+
#![allow(dead_code)]
97

108
#[macro_use]
119
extern crate edition_lint_infer_outlives_macro;
1210

11+
// Test that the lint does not fire if the predicate is from the local crate,
12+
// but all the bounds are from an external macro.
1313
macro_rules! make_foo {
1414
($a:tt) => {
15-
struct Foo<$a, 'b> where 'b: $a {
15+
struct Foo<$a, 'b: $a> {
16+
foo: &$a &'b (),
17+
}
18+
19+
struct FooWhere<$a, 'b> where 'b: $a {
1620
foo: &$a &'b (),
1721
}
1822
}
@@ -25,4 +29,109 @@ struct Bar<'a, 'b: 'a> {
2529
bar: &'a &'b (),
2630
}
2731

32+
struct BarWhere<'a, 'b> where 'b: 'a {
33+
//~^ ERROR: outlives requirements can be inferred
34+
bar: &'a &'b (),
35+
}
36+
37+
// Test that the lint *does* fire if the predicate is contained in a local macro.
38+
mod everything_inside {
39+
macro_rules! m {
40+
('b: 'a) => {
41+
struct Foo<'a, 'b: 'a>(&'a &'b ());
42+
//~^ ERROR: outlives requirements can be inferred
43+
struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a;
44+
//~^ ERROR: outlives requirements can be inferred
45+
struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a;
46+
//~^ ERROR: outlives requirements can be inferred
47+
};
48+
}
49+
m!('b: 'a);
50+
}
51+
52+
mod inner_lifetime_outside_colon_inside {
53+
macro_rules! m {
54+
($b:lifetime: 'a) => {
55+
struct Foo<'a, $b: 'a>(&'a &$b ());
56+
//~^ ERROR: outlives requirements can be inferred
57+
struct Bar<'a, $b>(&'a &$b ()) where $b: 'a;
58+
//~^ ERROR: outlives requirements can be inferred
59+
struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a;
60+
//~^ ERROR: outlives requirements can be inferred
61+
}
62+
}
63+
m!('b: 'a);
64+
}
65+
66+
mod outer_lifetime_outside_colon_inside {
67+
macro_rules! m {
68+
('b: $a:lifetime) => {
69+
struct Foo<$a, 'b: $a>(&$a &'b ());
70+
struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a;
71+
struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a;
72+
}
73+
}
74+
m!('b: 'a);
75+
}
76+
77+
mod both_lifetimes_outside_colon_inside {
78+
macro_rules! m {
79+
($b:lifetime: $a:lifetime) => {
80+
struct Foo<$a, $b: $a>(&$a &$b ());
81+
struct Bar<$a, $b>(&$a &$b ()) where $b: $a;
82+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a;
83+
}
84+
}
85+
m!('b: 'a);
86+
}
87+
88+
mod everything_outside {
89+
macro_rules! m {
90+
($b:lifetime $colon:tt $a:lifetime) => {
91+
struct Foo<$a, $b $colon $a>(&$a &$b ());
92+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
93+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
94+
}
95+
}
96+
m!('b: 'a);
97+
}
98+
99+
mod everything_outside_with_tt_inner {
100+
macro_rules! m {
101+
($b:tt $colon:tt $a:lifetime) => {
102+
struct Foo<$a, $b $colon $a>(&$a &$b ());
103+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
104+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
105+
}
106+
}
107+
m!('b: 'a);
108+
}
109+
110+
// FIXME: These should be consistent.
111+
mod everything_outside_with_tt_outer {
112+
macro_rules! m {
113+
($b:lifetime $colon:tt $a:tt) => {
114+
struct Foo<$a, $b $colon $a>(&$a &$b ());
115+
//~^ ERROR: outlives requirements can be inferred
116+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
117+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
118+
}
119+
}
120+
m!('b: 'a);
121+
}
122+
123+
mod everything_outside_with_tt_both {
124+
macro_rules! m {
125+
($b:tt $colon:tt $a:tt) => {
126+
struct Foo<$a, $b $colon $a>(&$a &$b ());
127+
//~^ ERROR: outlives requirements can be inferred
128+
struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
129+
//~^ ERROR: outlives requirements can be inferred
130+
struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
131+
//~^ ERROR: outlives requirements can be inferred
132+
}
133+
}
134+
m!('b: 'a);
135+
}
136+
28137
fn main() {}
Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,110 @@
11
error: outlives requirements can be inferred
2-
--> $DIR/edition-lint-infer-outlives-macro.rs:23:18
2+
--> $DIR/edition-lint-infer-outlives-macro.rs:27:18
33
|
44
LL | struct Bar<'a, 'b: 'a> {
55
| ^^^^ help: remove this bound
66
|
77
note: the lint level is defined here
8-
--> $DIR/edition-lint-infer-outlives-macro.rs:8:9
8+
--> $DIR/edition-lint-infer-outlives-macro.rs:5:9
99
|
1010
LL | #![deny(explicit_outlives_requirements)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: aborting due to previous error
13+
error: outlives requirements can be inferred
14+
--> $DIR/edition-lint-infer-outlives-macro.rs:32:24
15+
|
16+
LL | struct BarWhere<'a, 'b> where 'b: 'a {
17+
| ^^^^^^^^^^^^^ help: remove this bound
18+
19+
error: outlives requirements can be inferred
20+
--> $DIR/edition-lint-infer-outlives-macro.rs:41:30
21+
|
22+
LL | struct Foo<'a, 'b: 'a>(&'a &'b ());
23+
| ^^^^ help: remove this bound
24+
...
25+
LL | m!('b: 'a);
26+
| ---------- in this macro invocation
27+
|
28+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
29+
30+
error: outlives requirements can be inferred
31+
--> $DIR/edition-lint-infer-outlives-macro.rs:43:44
32+
|
33+
LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a;
34+
| ^^^^^^^^^^^^ help: remove this bound
35+
...
36+
LL | m!('b: 'a);
37+
| ---------- in this macro invocation
38+
|
39+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
40+
41+
error: outlives requirements can be inferred
42+
--> $DIR/edition-lint-infer-outlives-macro.rs:45:61
43+
|
44+
LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a;
45+
| ^^^^^^ help: remove this bound
46+
...
47+
LL | m!('b: 'a);
48+
| ---------- in this macro invocation
49+
|
50+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
51+
52+
error: outlives requirements can be inferred
53+
--> $DIR/edition-lint-infer-outlives-macro.rs:55:30
54+
|
55+
LL | struct Foo<'a, $b: 'a>(&'a &$b ());
56+
| ^^^^ help: remove this bound
57+
...
58+
LL | m!('b: 'a);
59+
| ---------- in this macro invocation
60+
|
61+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
62+
63+
error: outlives requirements can be inferred
64+
--> $DIR/edition-lint-infer-outlives-macro.rs:57:44
65+
|
66+
LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a;
67+
| ^^^^^^^^^^^^ help: remove this bound
68+
...
69+
LL | m!('b: 'a);
70+
| ---------- in this macro invocation
71+
|
72+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
73+
74+
error: outlives requirements can be inferred
75+
--> $DIR/edition-lint-infer-outlives-macro.rs:59:61
76+
|
77+
LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a;
78+
| ^^^^^^ help: remove this bound
79+
...
80+
LL | m!('b: 'a);
81+
| ---------- in this macro invocation
82+
|
83+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
84+
85+
error: outlives requirements can be inferred
86+
--> $DIR/edition-lint-infer-outlives-macro.rs:114:31
87+
|
88+
LL | struct Foo<$a, $b $colon $a>(&$a &$b ());
89+
| ^^^^^^^^^ help: remove this bound
90+
91+
error: outlives requirements can be inferred
92+
--> $DIR/edition-lint-infer-outlives-macro.rs:126:31
93+
|
94+
LL | struct Foo<$a, $b $colon $a>(&$a &$b ());
95+
| ^^^^^^^^^ help: remove this bound
96+
97+
error: outlives requirements can be inferred
98+
--> $DIR/edition-lint-infer-outlives-macro.rs:128:50
99+
|
100+
LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
101+
| ^^^^^^^^^^^^ help: remove this bound
102+
103+
error: outlives requirements can be inferred
104+
--> $DIR/edition-lint-infer-outlives-macro.rs:130:61
105+
|
106+
LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
107+
| ^^^^^^^^^^^^ help: remove this bound
108+
109+
error: aborting due to 12 previous errors
14110

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
let _f: f32 = 0xAAf32;
3+
//~^ ERROR mismatched types
4+
//~| HELP rewrite this
5+
6+
let _f: f32 = 0xAB_f32;
7+
//~^ ERROR mismatched types
8+
//~| HELP rewrite this
9+
10+
let _f: f64 = 0xFF_f64;
11+
//~^ ERROR mismatched types
12+
//~| HELP rewrite this
13+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/bad-hex-float-lit.rs:2:19
3+
|
4+
LL | let _f: f32 = 0xAAf32;
5+
| --- ^^^^^^^ expected `f32`, found integer
6+
| |
7+
| expected due to this
8+
|
9+
help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
10+
|
11+
LL | let _f: f32 = 0xAA as f32;
12+
| ~~~~~~~~~~~
13+
LL | let _f: f32 = 170_f32;
14+
| ~~~~~~~
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/bad-hex-float-lit.rs:6:19
18+
|
19+
LL | let _f: f32 = 0xAB_f32;
20+
| --- ^^^^^^^^ expected `f32`, found integer
21+
| |
22+
| expected due to this
23+
|
24+
help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
25+
|
26+
LL | let _f: f32 = 0xAB as f32;
27+
| ~~~~~~~~~~~
28+
LL | let _f: f32 = 171_f32;
29+
| ~~~~~~~
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/bad-hex-float-lit.rs:10:19
33+
|
34+
LL | let _f: f64 = 0xFF_f64;
35+
| --- ^^^^^^^^ expected `f64`, found integer
36+
| |
37+
| expected due to this
38+
|
39+
help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
40+
|
41+
LL | let _f: f64 = 0xFF as f64;
42+
| ~~~~~~~~~~~
43+
LL | let _f: f64 = 255_f64;
44+
| ~~~~~~~
45+
46+
error: aborting due to 3 previous errors
47+
48+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
fn as_ref() -> Option<Vec<u8>> {
2+
None
3+
}
4+
struct Type {
5+
option: Option<Vec<u8>>
6+
}
7+
trait Trait {
8+
fn foo(&self) -> Vec<u8>;
9+
}
10+
impl Trait for Option<Vec<u8>> {
11+
fn foo(&self) -> Vec<u8> {
12+
vec![1, 2, 3]
13+
}
14+
}
15+
16+
impl Type {
17+
fn method(&self) -> Option<Vec<u8>> {
18+
self.option..as_ref().map(|x| x)
19+
//~^ ERROR E0308
20+
}
21+
fn method2(&self) -> &u8 {
22+
self.option..foo().get(0)
23+
//~^ ERROR E0425
24+
//~| ERROR E0308
25+
}
26+
}
27+
28+
fn main() {
29+
let _ = Type { option: None }.method();
30+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0425]: cannot find function `foo` in this scope
2+
--> $DIR/method-access-to-range-literal-typo.rs:22:22
3+
|
4+
LL | self.option..foo().get(0)
5+
| ^^^ not found in this scope
6+
|
7+
help: you might have meant to write `.` instead of `..`
8+
|
9+
LL - self.option..foo().get(0)
10+
LL + self.option.foo().get(0)
11+
|
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/method-access-to-range-literal-typo.rs:18:9
15+
|
16+
LL | fn method(&self) -> Option<Vec<u8>> {
17+
| --------------- expected `Option<Vec<u8>>` because of return type
18+
LL | self.option..as_ref().map(|x| x)
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
20+
|
21+
= note: expected enum `Option<_>`
22+
found struct `std::ops::Range<Option<_>>`
23+
help: you likely meant to write a method call instead of a range
24+
|
25+
LL - self.option..as_ref().map(|x| x)
26+
LL + self.option.as_ref().map(|x| x)
27+
|
28+
29+
error[E0308]: mismatched types
30+
--> $DIR/method-access-to-range-literal-typo.rs:22:9
31+
|
32+
LL | fn method2(&self) -> &u8 {
33+
| --- expected `&u8` because of return type
34+
LL | self.option..foo().get(0)
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&u8`, found struct `Range`
36+
|
37+
= note: expected reference `&u8`
38+
found struct `std::ops::Range<Option<Vec<u8>>>`
39+
help: you likely meant to write a method call instead of a range
40+
|
41+
LL - self.option..foo().get(0)
42+
LL + self.option.foo().get(0)
43+
|
44+
45+
error: aborting due to 3 previous errors
46+
47+
Some errors have detailed explanations: E0308, E0425.
48+
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)
Please sign in to comment.