Auto merge of #118434 - matthiaskrgr:rollup-k1upt8b, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #118342 (Dont suggest `!` for path in function call if it has generic args)
 - #118383 (Address unused tuple struct fields in the standard library)
 - #118401 (`rustc_ast_lowering` cleanups)
 - #118409 (format_foreign.rs: unwrap return Option value for `fn position`, as it always returns Some)
 - #118413 (Fix the issue of suggesting unwrap/expect for shorthand field)
 - #118425 (Update cargo)
 - #118429 (Fix a typo in a `format_args!` note)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-11-29 06:23:14 +00:00
commit e9b7bf0114
25 changed files with 490 additions and 133 deletions

View file

@ -530,7 +530,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.mark_span_with_reason(
DesugaringKind::TryBlock,
expr.span,
this.allow_try_trait.clone(),
Some(this.allow_try_trait.clone()),
),
expr,
)
@ -538,7 +538,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let try_span = this.mark_span_with_reason(
DesugaringKind::TryBlock,
this.tcx.sess.source_map().end_point(body.span),
this.allow_try_trait.clone(),
Some(this.allow_try_trait.clone()),
);
(try_span, this.expr_unit(try_span))
@ -618,8 +618,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
// Resume argument type: `ResumeTy`
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
let unstable_span = self.mark_span_with_reason(
DesugaringKind::Async,
span,
Some(self.allow_gen_future.clone()),
);
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
let input_ty = hir::Ty {
hir_id: self.next_id(),
@ -741,7 +744,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let unstable_span = self.mark_span_with_reason(
DesugaringKind::Async,
span,
self.allow_gen_future.clone(),
Some(self.allow_gen_future.clone()),
);
self.lower_attrs(
inner_hir_id,
@ -788,7 +791,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let gen_future_span = self.mark_span_with_reason(
DesugaringKind::Await,
full_span,
self.allow_gen_future.clone(),
Some(self.allow_gen_future.clone()),
);
let expr = self.lower_expr_mut(expr);
let expr_hir_id = expr.hir_id;
@ -1646,13 +1649,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let unstable_span = self.mark_span_with_reason(
DesugaringKind::QuestionMark,
span,
self.allow_try_trait.clone(),
Some(self.allow_try_trait.clone()),
);
let try_span = self.tcx.sess.source_map().end_point(span);
let try_span = self.mark_span_with_reason(
DesugaringKind::QuestionMark,
try_span,
self.allow_try_trait.clone(),
Some(self.allow_try_trait.clone()),
);
// `Try::branch(<expr>)`
@ -1745,7 +1748,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let unstable_span = self.mark_span_with_reason(
DesugaringKind::YeetExpr,
span,
self.allow_try_trait.clone(),
Some(self.allow_try_trait.clone()),
);
let from_yeet_expr = self.wrap_in_try_constructor(

View file

@ -10,7 +10,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::{Span, DUMMY_SP};
/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
pub(super) struct NodeCollector<'a, 'hir> {
struct NodeCollector<'a, 'hir> {
tcx: TyCtxt<'hir>,
bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,

View file

@ -7,7 +7,6 @@ use hir::definitions::DefPathData;
use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@ -55,42 +54,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
owner: NodeId,
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
) {
let allow_gen_future = Some(if self.tcx.features().async_fn_track_caller {
[sym::gen_future, sym::closure_track_caller][..].into()
} else {
[sym::gen_future][..].into()
});
let mut lctx = LoweringContext {
// Pseudo-globals.
tcx: self.tcx,
resolver: self.resolver,
arena: self.tcx.hir_arena,
// HirId handling.
bodies: Vec::new(),
attrs: SortedMap::default(),
children: Vec::default(),
current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(),
trait_map: Default::default(),
// Lowering state.
catch_scope: None,
loop_scope: None,
is_in_loop_condition: false,
is_in_trait_impl: false,
is_in_dyn_type: false,
coroutine_kind: None,
task_context: None,
current_item: None,
impl_trait_defs: Vec::new(),
impl_trait_bounds: Vec::new(),
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
allow_gen_future,
generics_def_id_map: Default::default(),
host_param_id: None,
};
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
for (def_id, info) in lctx.children {
@ -136,39 +100,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
let def_id = self.resolver.node_id_to_def_id[&item.id];
let parent_id = self.tcx.local_parent(def_id);
let parent_hir = self.lower_node(parent_id).unwrap();
self.with_lctx(item.id, |lctx| {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
match parent_hir.node().expect_item().kind {
hir::ItemKind::Impl(impl_) => {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
}
hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => {
lctx.host_param_id = generics
.params
.iter()
.find(|param| {
parent_hir
.attrs
.get(param.hir_id.local_id)
.iter()
.any(|attr| attr.has_name(sym::rustc_host))
})
.map(|param| param.def_id);
}
_ => {}
}
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
}
})
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir))
}
fn lower_foreign_item(&mut self, item: &ForeignItem) {
@ -611,6 +545,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn lower_assoc_item(
&mut self,
item: &AssocItem,
ctxt: AssocCtxt,
parent_hir: &'hir hir::OwnerInfo<'hir>,
) -> hir::OwnerNode<'hir> {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
match parent_hir.node().expect_item().kind {
hir::ItemKind::Impl(impl_) => {
self.is_in_trait_impl = impl_.of_trait.is_some();
}
hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => {
self.host_param_id = generics
.params
.iter()
.find(|param| {
parent_hir
.attrs
.get(param.hir_id.local_id)
.iter()
.any(|attr| attr.has_name(sym::rustc_host))
})
.map(|param| param.def_id);
}
_ => {}
}
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
}
}
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let owner_id = hir_id.expect_owner();

View file

@ -35,7 +35,6 @@
#![doc(rust_logo)]
#![feature(box_patterns)]
#![feature(let_chains)]
#![feature(never_type)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
@ -132,8 +131,8 @@ struct LoweringContext<'a, 'hir> {
/// NodeIds that are lowered inside the current HIR owner.
node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>,
allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>,
allow_try_trait: Lrc<[Symbol]>,
allow_gen_future: Lrc<[Symbol]>,
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
@ -144,6 +143,46 @@ struct LoweringContext<'a, 'hir> {
host_param_id: Option<LocalDefId>,
}
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
Self {
// Pseudo-globals.
tcx,
resolver: resolver,
arena: tcx.hir_arena,
// HirId handling.
bodies: Vec::new(),
attrs: SortedMap::default(),
children: Vec::default(),
current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(),
trait_map: Default::default(),
// Lowering state.
catch_scope: None,
loop_scope: None,
is_in_loop_condition: false,
is_in_trait_impl: false,
is_in_dyn_type: false,
coroutine_kind: None,
task_context: None,
current_item: None,
impl_trait_defs: Vec::new(),
impl_trait_bounds: Vec::new(),
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
allow_gen_future: if tcx.features().async_fn_track_caller {
[sym::gen_future, sym::closure_track_caller].into()
} else {
[sym::gen_future].into()
},
generics_def_id_map: Default::default(),
host_param_id: None,
}
}
}
trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;

View file

@ -108,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
}
}
pub fn lifetimes_in_bounds(
pub(crate) fn lifetimes_in_bounds(
resolver: &ResolverAstLowering,
bounds: &GenericBounds,
) -> Vec<Lifetime> {

View file

@ -18,7 +18,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc(self.lower_pat_mut(pattern))
}
pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
ensure_sufficient_stack(|| {
// loop here to avoid recursion
let node = loop {

View file

@ -2352,7 +2352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Applicability::MaybeIncorrect,
);
} else {
err.note("the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used");
err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used");
err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
}
suggested = true;

View file

@ -672,30 +672,22 @@ fn report_missing_placeholders(
if explained.contains(&sub) {
continue;
}
explained.insert(sub.clone());
explained.insert(sub);
if !found_foreign {
found_foreign = true;
show_doc_note = true;
}
if let Some(inner_sp) = pos {
let sp = fmt_span.from_inner(inner_sp);
let sp = fmt_span.from_inner(pos);
if success {
suggestions.push((sp, trn));
} else {
diag.span_note(
sp,
format!("format specifiers use curly braces, and {}", trn),
);
}
if success {
suggestions.push((sp, trn));
} else {
if success {
diag.help(format!("`{}` should be written as `{}`", sub, trn));
} else {
diag.note(format!("`{}` should use curly braces, and {}", sub, trn));
}
diag.span_note(
sp,
format!("format specifiers use curly braces, and {}", trn),
);
}
}

View file

@ -19,10 +19,10 @@ pub(crate) mod printf {
}
}
pub fn position(&self) -> Option<InnerSpan> {
pub fn position(&self) -> InnerSpan {
match self {
Substitution::Format(fmt) => Some(fmt.position),
&Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
Substitution::Format(fmt) => fmt.position,
&Substitution::Escape((start, end)) => InnerSpan::new(start, end),
}
}
@ -302,10 +302,9 @@ pub(crate) mod printf {
fn next(&mut self) -> Option<Self::Item> {
let (mut sub, tail) = parse_next_substitution(self.s)?;
self.s = tail;
if let Some(InnerSpan { start, end }) = sub.position() {
sub.set_position(start + self.pos, end + self.pos);
self.pos += end;
}
let InnerSpan { start, end } = sub.position();
sub.set_position(start + self.pos, end + self.pos);
self.pos += end;
Some(sub)
}
@ -629,9 +628,9 @@ pub mod shell {
}
}
pub fn position(&self) -> Option<InnerSpan> {
pub fn position(&self) -> InnerSpan {
let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
Some(InnerSpan::new(pos.0, pos.1))
InnerSpan::new(pos.0, pos.1)
}
pub fn set_position(&mut self, start: usize, end: usize) {
@ -664,10 +663,9 @@ pub mod shell {
fn next(&mut self) -> Option<Self::Item> {
let (mut sub, tail) = parse_next_substitution(self.s)?;
self.s = tail;
if let Some(InnerSpan { start, end }) = sub.position() {
sub.set_position(start + self.pos, end + self.pos);
self.pos += end;
}
let InnerSpan { start, end } = sub.position();
sub.set_position(start + self.pos, end + self.pos);
self.pos += end;
Some(sub)
}

View file

@ -492,7 +492,7 @@ where
let returned_walk =
return_value.take().into_iter().map(|walk| (*successor_node, Some(walk)));
let successor_walk = successors.by_ref().map(|successor_node| {
let successor_walk = successors.map(|successor_node| {
debug!(?node, ?successor_node);
(successor_node, self.inspect_node(successor_node))
});

View file

@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> {
pub span: Span,
#[suggestion_part(code = "")]
pub borrow_removal_span: Option<Span>,
pub sugg: &'static str,
pub sugg: String,
pub expected: Ty<'tcx>,
pub found: Ty<'tcx>,
}

View file

@ -442,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
)
});
let prefix_wrap = |sugg: &str| {
if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
format!(": {}{}", name, sugg)
} else {
sugg.to_string()
}
};
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
// but those checks need to be a bit more delicate and the benefit is diminishing.
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
let sugg = prefix_wrap(".as_ref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_ref()",
sugg,
expected,
found,
borrow_removal_span,
@ -458,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, deref_ty, peeled)
&& error_tys_equate_as_ref
{
let sugg = prefix_wrap(".as_deref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_deref()",
sugg,
expected,
found,
borrow_removal_span,
@ -474,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.can_eq(self.param_env, found, expected)
})
{
let sugg = prefix_wrap(".map(|x| x.as_str())");
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
fluent::hir_typeck_convert_to_str,
".map(|x| x.as_str())",
sugg,
Applicability::MachineApplicable,
);
return true;
@ -628,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("use `Box::pin`");
}
_ => {
let prefix = if let Some(name) =
self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
{
format!("{}: ", name)
} else {
String::new()
};
let suggestion = vec![
(expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")),
(expr.span.shrink_to_hi(), ")".to_string()),
];
err.multipart_suggestion(
"you need to pin and box this expression",
vec![
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
(expr.span.shrink_to_hi(), ")".to_string()),
],
suggestion,
Applicability::MaybeIncorrect,
);
}
@ -1214,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span = parent_callsite;
}
let sugg = if expr.precedence().order() >= PREC_POSTFIX {
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@ -1222,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(span.shrink_to_hi(), ").into()".to_owned()),
]
};
if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
}
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
@ -1811,6 +1834,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".expect(\"REASON\")",
)
};
let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!(": {ident}{sugg}"),
None => sugg.to_string(),
};
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
msg,

View file

@ -744,6 +744,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err,
span,
source,
path,
res,
&path_str,
&base_error.fallback_label,
@ -1328,6 +1329,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err: &mut Diagnostic,
span: Span,
source: PathSource<'_>,
path: &[Segment],
res: Res,
path_str: &str,
fallback_label: &str,
@ -1523,12 +1525,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
| PathSource::Struct,
) => {
err.span_label(span, fallback_label.to_string());
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
"!",
Applicability::MaybeIncorrect,
);
// Don't suggest `!` for a macro invocation if there are generic args
if path
.last()
.is_some_and(|segment| !segment.has_generic_args && !segment.has_lifetime_args)
{
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
"!",
Applicability::MaybeIncorrect,
);
}
if path_str == "try" && span.is_rust_2015() {
err.note("if you want the `try` keyword, you need Rust 2018 or later");
}

View file

@ -222,7 +222,6 @@ rustc_index::newtype_index! {
}
}
// njn: I don't understand these
impl<E: Encoder> Encodable<E> for DefIndex {
default fn encode(&self, _: &mut E) {
panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());

View file

@ -171,6 +171,7 @@ struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
/// An opaque representation of `WithHeader<H>` to avoid the
/// projection invariance of `<T as Pointee>::Metadata`.
#[repr(transparent)]
#[allow(unused_tuple_struct_fields)] // Field only used through `WithHeader` type above.
struct WithOpaqueHeader(NonNull<u8>);
impl WithOpaqueHeader {

@ -1 +1 @@
Subproject commit 9b13310ca596020a737aaa47daa4ed9ff8898a2f
Subproject commit 26333c732095d207aa05932ce863d850fb309386

View file

@ -9,7 +9,7 @@ LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3);
LL | bar(x);
| - borrow later used here
|
= note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used
= note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used
= note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -24,7 +24,7 @@ LL |
LL | bar(foo);
| --- borrow later used here
|
= note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used
= note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used
= note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -0,0 +1,20 @@
// run-rustfix
#![allow(unused, dead_code)]
#[derive(Clone, Copy)]
struct Stuff {
count: i32,
}
struct Error;
fn demo() -> Result<Stuff, Error> {
let count = Ok(1);
Ok(Stuff { count: count? }) //~ ERROR mismatched types
}
fn demo_unwrap() -> Stuff {
let count = Some(1);
Stuff { count: count.expect("REASON") } //~ ERROR mismatched types
}
fn main() {}

View file

@ -0,0 +1,20 @@
// run-rustfix
#![allow(unused, dead_code)]
#[derive(Clone, Copy)]
struct Stuff {
count: i32,
}
struct Error;
fn demo() -> Result<Stuff, Error> {
let count = Ok(1);
Ok(Stuff { count }) //~ ERROR mismatched types
}
fn demo_unwrap() -> Stuff {
let count = Some(1);
Stuff { count } //~ ERROR mismatched types
}
fn main() {}

View file

@ -0,0 +1,29 @@
error[E0308]: mismatched types
--> $DIR/issue-118145-unwrap-for-shorthand.rs:12:16
|
LL | Ok(Stuff { count })
| ^^^^^ expected `i32`, found `Result<{integer}, _>`
|
= note: expected type `i32`
found enum `Result<{integer}, _>`
help: use the `?` operator to extract the `Result<{integer}, _>` value, propagating a `Result::Err` value to the caller
|
LL | Ok(Stuff { count: count? })
| ++++++++
error[E0308]: mismatched types
--> $DIR/issue-118145-unwrap-for-shorthand.rs:17:13
|
LL | Stuff { count }
| ^^^^^ expected `i32`, found `Option<{integer}>`
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None`
|
LL | Stuff { count: count.expect("REASON") }
| ++++++++++++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,77 @@
// run-rustfix
// edition:2021
#![allow(dead_code)]
#![allow(unused_variables)]
use std::future::Future;
use std::pin::Pin;
fn test1() {
let string = String::from("Hello, world");
struct Demo<'a> {
option: Option<&'a str>,
}
let option: Option<String> = Some(string.clone());
let s = Demo { option: option.as_deref() }; //~ ERROR mismatched types
}
fn test2() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types
}
fn test3() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let option_ref_ref = option_ref.as_ref();
let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types
}
fn test4() {
let a = 1;
struct Demo {
a: String,
}
let s = Demo { a: a.to_string() }; //~ ERROR mismatched types
}
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
fn test5() {
let a = async { 42 };
struct Demo {
a: BoxFuture<'static, i32>,
}
let s = Demo { a: Box::pin(a) }; //~ ERROR mismatched types
}
fn test6() {
struct A;
struct B;
impl From<B> for A {
fn from(_: B) -> Self {
A
}
}
struct Demo {
a: A,
}
let a = B;
let s = Demo { a: a.into() }; //~ ERROR mismatched types
}
fn main() {}

View file

@ -0,0 +1,77 @@
// run-rustfix
// edition:2021
#![allow(dead_code)]
#![allow(unused_variables)]
use std::future::Future;
use std::pin::Pin;
fn test1() {
let string = String::from("Hello, world");
struct Demo<'a> {
option: Option<&'a str>,
}
let option: Option<String> = Some(string.clone());
let s = Demo { option }; //~ ERROR mismatched types
}
fn test2() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let s = Demo { option_ref }; //~ ERROR mismatched types
}
fn test3() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let option_ref_ref = option_ref.as_ref();
let s = Demo { option_ref_ref }; //~ ERROR mismatched types
}
fn test4() {
let a = 1;
struct Demo {
a: String,
}
let s = Demo { a }; //~ ERROR mismatched types
}
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
fn test5() {
let a = async { 42 };
struct Demo {
a: BoxFuture<'static, i32>,
}
let s = Demo { a }; //~ ERROR mismatched types
}
fn test6() {
struct A;
struct B;
impl From<B> for A {
fn from(_: B) -> Self {
A
}
}
struct Demo {
a: A,
}
let a = B;
let s = Demo { a }; //~ ERROR mismatched types
}
fn main() {}

View file

@ -0,0 +1,80 @@
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:16:20
|
LL | let s = Demo { option };
| ^^^^^^ expected `Option<&str>`, found `Option<String>`
|
= note: expected enum `Option<&str>`
found enum `Option<String>`
help: try using `: option.as_deref()` to convert `Option<String>` to `Option<&str>`
|
LL | let s = Demo { option: option.as_deref() };
| +++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:27:20
|
LL | let s = Demo { option_ref };
| ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>`
|
= note: expected enum `Option<&str>`
found enum `Option<&String>`
help: try converting the passed type into a `&str`
|
LL | let s = Demo { option_ref: option_ref.map(|x| x.as_str()) };
| ++++++++++++++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:40:20
|
LL | let s = Demo { option_ref_ref };
| ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>`
|
= note: expected enum `Option<&str>`
found enum `Option<&&String>`
help: try converting the passed type into a `&str`
|
LL | let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) };
| ++++++++++++++++++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:48:20
|
LL | let s = Demo { a };
| ^ expected `String`, found integer
|
help: try using a conversion method
|
LL | let s = Demo { a: a.to_string() };
| ++ ++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20
|
LL | let a = async { 42 };
| ------------ the found `async` block
...
LL | let s = Demo { a };
| ^ expected `Pin<Box<...>>`, found `async` block
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}`
help: you need to pin and box this expression
|
LL | let s = Demo { a: Box::pin(a) };
| ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:74:20
|
LL | let s = Demo { a };
| ^ expected `A`, found `B`
|
help: call `Into::into` on this expression to convert `B` into `A`
|
LL | let s = Demo { a: a.into() };
| ++ +++++++
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,4 @@
fn main() {
let zero = assert_eq::<()>();
//~^ ERROR expected function, found macro `assert_eq`
}

View file

@ -0,0 +1,9 @@
error[E0423]: expected function, found macro `assert_eq`
--> $DIR/resolve-dont-hint-macro.rs:2:16
|
LL | let zero = assert_eq::<()>();
| ^^^^^^^^^^^^^^^ not a function
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0423`.