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:
commit
e9b7bf0114
25 changed files with 490 additions and 133 deletions
|
@ -530,7 +530,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
this.mark_span_with_reason(
|
this.mark_span_with_reason(
|
||||||
DesugaringKind::TryBlock,
|
DesugaringKind::TryBlock,
|
||||||
expr.span,
|
expr.span,
|
||||||
this.allow_try_trait.clone(),
|
Some(this.allow_try_trait.clone()),
|
||||||
),
|
),
|
||||||
expr,
|
expr,
|
||||||
)
|
)
|
||||||
|
@ -538,7 +538,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let try_span = this.mark_span_with_reason(
|
let try_span = this.mark_span_with_reason(
|
||||||
DesugaringKind::TryBlock,
|
DesugaringKind::TryBlock,
|
||||||
this.tcx.sess.source_map().end_point(body.span),
|
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))
|
(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)));
|
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
||||||
|
|
||||||
// Resume argument type: `ResumeTy`
|
// Resume argument type: `ResumeTy`
|
||||||
let unstable_span =
|
let unstable_span = self.mark_span_with_reason(
|
||||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
DesugaringKind::Async,
|
||||||
|
span,
|
||||||
|
Some(self.allow_gen_future.clone()),
|
||||||
|
);
|
||||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
||||||
let input_ty = hir::Ty {
|
let input_ty = hir::Ty {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
|
@ -741,7 +744,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let unstable_span = self.mark_span_with_reason(
|
let unstable_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::Async,
|
DesugaringKind::Async,
|
||||||
span,
|
span,
|
||||||
self.allow_gen_future.clone(),
|
Some(self.allow_gen_future.clone()),
|
||||||
);
|
);
|
||||||
self.lower_attrs(
|
self.lower_attrs(
|
||||||
inner_hir_id,
|
inner_hir_id,
|
||||||
|
@ -788,7 +791,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let gen_future_span = self.mark_span_with_reason(
|
let gen_future_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::Await,
|
DesugaringKind::Await,
|
||||||
full_span,
|
full_span,
|
||||||
self.allow_gen_future.clone(),
|
Some(self.allow_gen_future.clone()),
|
||||||
);
|
);
|
||||||
let expr = self.lower_expr_mut(expr);
|
let expr = self.lower_expr_mut(expr);
|
||||||
let expr_hir_id = expr.hir_id;
|
let expr_hir_id = expr.hir_id;
|
||||||
|
@ -1646,13 +1649,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let unstable_span = self.mark_span_with_reason(
|
let unstable_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::QuestionMark,
|
DesugaringKind::QuestionMark,
|
||||||
span,
|
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.tcx.sess.source_map().end_point(span);
|
||||||
let try_span = self.mark_span_with_reason(
|
let try_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::QuestionMark,
|
DesugaringKind::QuestionMark,
|
||||||
try_span,
|
try_span,
|
||||||
self.allow_try_trait.clone(),
|
Some(self.allow_try_trait.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// `Try::branch(<expr>)`
|
// `Try::branch(<expr>)`
|
||||||
|
@ -1745,7 +1748,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let unstable_span = self.mark_span_with_reason(
|
let unstable_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::YeetExpr,
|
DesugaringKind::YeetExpr,
|
||||||
span,
|
span,
|
||||||
self.allow_try_trait.clone(),
|
Some(self.allow_try_trait.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let from_yeet_expr = self.wrap_in_try_constructor(
|
let from_yeet_expr = self.wrap_in_try_constructor(
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
|
/// 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>,
|
tcx: TyCtxt<'hir>,
|
||||||
|
|
||||||
bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
||||||
|
|
|
@ -7,7 +7,6 @@ use hir::definitions::DefPathData;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::AssocCtxt;
|
use rustc_ast::visit::AssocCtxt;
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
|
@ -55,42 +54,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
owner: NodeId,
|
owner: NodeId,
|
||||||
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
||||||
) {
|
) {
|
||||||
let allow_gen_future = Some(if self.tcx.features().async_fn_track_caller {
|
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
|
||||||
[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,
|
|
||||||
};
|
|
||||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||||
|
|
||||||
for (def_id, info) in lctx.children {
|
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) {
|
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
|
||||||
let def_id = self.resolver.node_id_to_def_id[&item.id];
|
let def_id = self.resolver.node_id_to_def_id[&item.id];
|
||||||
|
|
||||||
let parent_id = self.tcx.local_parent(def_id);
|
let parent_id = self.tcx.local_parent(def_id);
|
||||||
let parent_hir = self.lower_node(parent_id).unwrap();
|
let parent_hir = self.lower_node(parent_id).unwrap();
|
||||||
self.with_lctx(item.id, |lctx| {
|
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_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_) => {
|
|
||||||
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)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_foreign_item(&mut self, item: &ForeignItem) {
|
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> {
|
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
|
||||||
let hir_id = self.lower_node_id(i.id);
|
let hir_id = self.lower_node_id(i.id);
|
||||||
let owner_id = hir_id.expect_owner();
|
let owner_id = hir_id.expect_owner();
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(never_type)]
|
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
@ -132,8 +131,8 @@ struct LoweringContext<'a, 'hir> {
|
||||||
/// NodeIds that are lowered inside the current HIR owner.
|
/// NodeIds that are lowered inside the current HIR owner.
|
||||||
node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>,
|
node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>,
|
||||||
|
|
||||||
allow_try_trait: Option<Lrc<[Symbol]>>,
|
allow_try_trait: Lrc<[Symbol]>,
|
||||||
allow_gen_future: Option<Lrc<[Symbol]>>,
|
allow_gen_future: Lrc<[Symbol]>,
|
||||||
|
|
||||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
/// 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
|
/// 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>,
|
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 {
|
trait ResolverAstLoweringExt {
|
||||||
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
|
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
|
||||||
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
|
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
|
||||||
|
|
|
@ -108,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lifetimes_in_bounds(
|
pub(crate) fn lifetimes_in_bounds(
|
||||||
resolver: &ResolverAstLowering,
|
resolver: &ResolverAstLowering,
|
||||||
bounds: &GenericBounds,
|
bounds: &GenericBounds,
|
||||||
) -> Vec<Lifetime> {
|
) -> Vec<Lifetime> {
|
||||||
|
|
|
@ -18,7 +18,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.arena.alloc(self.lower_pat_mut(pattern))
|
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(|| {
|
ensure_sufficient_stack(|| {
|
||||||
// loop here to avoid recursion
|
// loop here to avoid recursion
|
||||||
let node = loop {
|
let node = loop {
|
||||||
|
|
|
@ -2352,7 +2352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else {
|
} 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>");
|
err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
|
||||||
}
|
}
|
||||||
suggested = true;
|
suggested = true;
|
||||||
|
|
|
@ -672,30 +672,22 @@ fn report_missing_placeholders(
|
||||||
if explained.contains(&sub) {
|
if explained.contains(&sub) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
explained.insert(sub.clone());
|
explained.insert(sub);
|
||||||
|
|
||||||
if !found_foreign {
|
if !found_foreign {
|
||||||
found_foreign = true;
|
found_foreign = true;
|
||||||
show_doc_note = true;
|
show_doc_note = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(inner_sp) = pos {
|
let sp = fmt_span.from_inner(pos);
|
||||||
let sp = fmt_span.from_inner(inner_sp);
|
|
||||||
|
|
||||||
if success {
|
if success {
|
||||||
suggestions.push((sp, trn));
|
suggestions.push((sp, trn));
|
||||||
} else {
|
|
||||||
diag.span_note(
|
|
||||||
sp,
|
|
||||||
format!("format specifiers use curly braces, and {}", trn),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if success {
|
diag.span_note(
|
||||||
diag.help(format!("`{}` should be written as `{}`", sub, trn));
|
sp,
|
||||||
} else {
|
format!("format specifiers use curly braces, and {}", trn),
|
||||||
diag.note(format!("`{}` should use curly braces, and {}", sub, trn));
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ pub(crate) mod printf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(&self) -> Option<InnerSpan> {
|
pub fn position(&self) -> InnerSpan {
|
||||||
match self {
|
match self {
|
||||||
Substitution::Format(fmt) => Some(fmt.position),
|
Substitution::Format(fmt) => fmt.position,
|
||||||
&Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
|
&Substitution::Escape((start, end)) => InnerSpan::new(start, end),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,10 +302,9 @@ pub(crate) mod printf {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
||||||
self.s = tail;
|
self.s = tail;
|
||||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
let InnerSpan { start, end } = sub.position();
|
||||||
sub.set_position(start + self.pos, end + self.pos);
|
sub.set_position(start + self.pos, end + self.pos);
|
||||||
self.pos += end;
|
self.pos += end;
|
||||||
}
|
|
||||||
Some(sub)
|
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;
|
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) {
|
pub fn set_position(&mut self, start: usize, end: usize) {
|
||||||
|
@ -664,10 +663,9 @@ pub mod shell {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
||||||
self.s = tail;
|
self.s = tail;
|
||||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
let InnerSpan { start, end } = sub.position();
|
||||||
sub.set_position(start + self.pos, end + self.pos);
|
sub.set_position(start + self.pos, end + self.pos);
|
||||||
self.pos += end;
|
self.pos += end;
|
||||||
}
|
|
||||||
Some(sub)
|
Some(sub)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,7 @@ where
|
||||||
let returned_walk =
|
let returned_walk =
|
||||||
return_value.take().into_iter().map(|walk| (*successor_node, Some(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);
|
debug!(?node, ?successor_node);
|
||||||
(successor_node, self.inspect_node(successor_node))
|
(successor_node, self.inspect_node(successor_node))
|
||||||
});
|
});
|
||||||
|
|
|
@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[suggestion_part(code = "")]
|
#[suggestion_part(code = "")]
|
||||||
pub borrow_removal_span: Option<Span>,
|
pub borrow_removal_span: Option<Span>,
|
||||||
pub sugg: &'static str,
|
pub sugg: String,
|
||||||
pub expected: Ty<'tcx>,
|
pub expected: Ty<'tcx>,
|
||||||
pub found: Ty<'tcx>,
|
pub found: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
expected,
|
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`,
|
// 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.
|
// 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 {
|
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 {
|
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||||
span: expr.span.shrink_to_hi(),
|
span: expr.span.shrink_to_hi(),
|
||||||
sugg: ".as_ref()",
|
sugg,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
borrow_removal_span,
|
borrow_removal_span,
|
||||||
|
@ -458,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&& self.can_eq(self.param_env, deref_ty, peeled)
|
&& self.can_eq(self.param_env, deref_ty, peeled)
|
||||||
&& error_tys_equate_as_ref
|
&& error_tys_equate_as_ref
|
||||||
{
|
{
|
||||||
|
let sugg = prefix_wrap(".as_deref()");
|
||||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||||
span: expr.span.shrink_to_hi(),
|
span: expr.span.shrink_to_hi(),
|
||||||
sugg: ".as_deref()",
|
sugg,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
borrow_removal_span,
|
borrow_removal_span,
|
||||||
|
@ -474,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.can_eq(self.param_env, found, expected)
|
self.can_eq(self.param_env, found, expected)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
let sugg = prefix_wrap(".map(|x| x.as_str())");
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_hi(),
|
expr.span.shrink_to_hi(),
|
||||||
fluent::hir_typeck_convert_to_str,
|
fluent::hir_typeck_convert_to_str,
|
||||||
".map(|x| x.as_str())",
|
sugg,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
|
@ -628,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err.help("use `Box::pin`");
|
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(
|
err.multipart_suggestion(
|
||||||
"you need to pin and box this expression",
|
"you need to pin and box this expression",
|
||||||
vec![
|
suggestion,
|
||||||
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
|
|
||||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1214,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
span = parent_callsite;
|
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())]
|
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
|
@ -1222,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
(span.shrink_to_hi(), ").into()".to_owned()),
|
(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(
|
diag.multipart_suggestion(
|
||||||
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
|
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
|
||||||
sugg,
|
sugg,
|
||||||
|
@ -1811,6 +1834,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
".expect(\"REASON\")",
|
".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(
|
err.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_hi(),
|
expr.span.shrink_to_hi(),
|
||||||
msg,
|
msg,
|
||||||
|
|
|
@ -744,6 +744,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
err,
|
err,
|
||||||
span,
|
span,
|
||||||
source,
|
source,
|
||||||
|
path,
|
||||||
res,
|
res,
|
||||||
&path_str,
|
&path_str,
|
||||||
&base_error.fallback_label,
|
&base_error.fallback_label,
|
||||||
|
@ -1328,6 +1329,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
span: Span,
|
span: Span,
|
||||||
source: PathSource<'_>,
|
source: PathSource<'_>,
|
||||||
|
path: &[Segment],
|
||||||
res: Res,
|
res: Res,
|
||||||
path_str: &str,
|
path_str: &str,
|
||||||
fallback_label: &str,
|
fallback_label: &str,
|
||||||
|
@ -1523,12 +1525,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
| PathSource::Struct,
|
| PathSource::Struct,
|
||||||
) => {
|
) => {
|
||||||
err.span_label(span, fallback_label.to_string());
|
err.span_label(span, fallback_label.to_string());
|
||||||
err.span_suggestion_verbose(
|
|
||||||
span.shrink_to_hi(),
|
// Don't suggest `!` for a macro invocation if there are generic args
|
||||||
"use `!` to invoke the macro",
|
if path
|
||||||
"!",
|
.last()
|
||||||
Applicability::MaybeIncorrect,
|
.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() {
|
if path_str == "try" && span.is_rust_2015() {
|
||||||
err.note("if you want the `try` keyword, you need Rust 2018 or later");
|
err.note("if you want the `try` keyword, you need Rust 2018 or later");
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,6 @@ rustc_index::newtype_index! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// njn: I don't understand these
|
|
||||||
impl<E: Encoder> Encodable<E> for DefIndex {
|
impl<E: Encoder> Encodable<E> for DefIndex {
|
||||||
default fn encode(&self, _: &mut E) {
|
default fn encode(&self, _: &mut E) {
|
||||||
panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
|
panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
|
||||||
|
|
|
@ -171,6 +171,7 @@ struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
|
||||||
/// An opaque representation of `WithHeader<H>` to avoid the
|
/// An opaque representation of `WithHeader<H>` to avoid the
|
||||||
/// projection invariance of `<T as Pointee>::Metadata`.
|
/// projection invariance of `<T as Pointee>::Metadata`.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
#[allow(unused_tuple_struct_fields)] // Field only used through `WithHeader` type above.
|
||||||
struct WithOpaqueHeader(NonNull<u8>);
|
struct WithOpaqueHeader(NonNull<u8>);
|
||||||
|
|
||||||
impl WithOpaqueHeader {
|
impl WithOpaqueHeader {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9b13310ca596020a737aaa47daa4ed9ff8898a2f
|
Subproject commit 26333c732095d207aa05932ce863d850fb309386
|
|
@ -9,7 +9,7 @@ LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3);
|
||||||
LL | bar(x);
|
LL | bar(x);
|
||||||
| - borrow later used here
|
| - 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: 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)
|
= 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);
|
LL | bar(foo);
|
||||||
| --- borrow later used here
|
| --- 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: 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)
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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() {}
|
|
@ -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() {}
|
|
@ -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`.
|
4
tests/ui/resolve/resolve-dont-hint-macro.rs
Normal file
4
tests/ui/resolve/resolve-dont-hint-macro.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() {
|
||||||
|
let zero = assert_eq::<()>();
|
||||||
|
//~^ ERROR expected function, found macro `assert_eq`
|
||||||
|
}
|
9
tests/ui/resolve/resolve-dont-hint-macro.stderr
Normal file
9
tests/ui/resolve/resolve-dont-hint-macro.stderr
Normal 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`.
|
Loading…
Add table
Reference in a new issue