mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #121169 - GuillaumeGomez:rollup-oxk5d5j, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - #120777 (Bump Unicode to version 15.1.0, regenerate tables) - #120971 (Fix comment in core/src/str/validations.rs) - #121095 (Add extra indent spaces for rust-playground link) - #121109 (Add an ErrorGuaranteed to ast::TyKind::Err (attempt 2)) - #121119 (Make `async Fn` trait kind errors better) - #121141 (Fix closure kind docs) - #121145 (Update aarch64 target feature docs to match LLVM) - #121146 (Only point out non-diverging arms for match suggestions) - #121147 (Avoid debug logging entire MIR body) - #121155 (doc: add note about panicking examples for strict_overflow_ops) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
cefa14bf2f
@ -2136,10 +2136,12 @@ pub enum TyKind {
|
||||
ImplicitSelf,
|
||||
/// A macro in the type position.
|
||||
MacCall(P<MacCall>),
|
||||
/// Placeholder for a kind that has failed to be defined.
|
||||
Err,
|
||||
/// Placeholder for a `va_list`.
|
||||
CVarArgs,
|
||||
/// Sometimes we need a dummy value when no error has occurred.
|
||||
Dummy,
|
||||
/// Placeholder for a kind that has failed to be defined.
|
||||
Err(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
impl TyKind {
|
||||
|
@ -481,7 +481,12 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
let Ty { id, kind, span, tokens } = ty.deref_mut();
|
||||
vis.visit_id(id);
|
||||
match kind {
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {}
|
||||
TyKind::Infer
|
||||
| TyKind::ImplicitSelf
|
||||
| TyKind::Err(_)
|
||||
| TyKind::Dummy
|
||||
| TyKind::Never
|
||||
| TyKind::CVarArgs => {}
|
||||
TyKind::Slice(ty) => vis.visit_ty(ty),
|
||||
TyKind::Ptr(mt) => vis.visit_mt(mt),
|
||||
TyKind::Ref(lt, mt) => {
|
||||
@ -1649,7 +1654,7 @@ impl DummyAstNode for Ty {
|
||||
fn dummy() -> Self {
|
||||
Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: TyKind::Err,
|
||||
kind: TyKind::Dummy,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
|
||||
}
|
||||
TyKind::Typeof(expression) => visitor.visit_anon_const(expression),
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
|
||||
TyKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
TyKind::Never | TyKind::CVarArgs => {}
|
||||
TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
|
||||
|
@ -1286,7 +1286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
|
||||
let kind = match &t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
TyKind::Err => hir::TyKind::Err(self.dcx().has_errors().unwrap()),
|
||||
TyKind::Err(guar) => hir::TyKind::Err(*guar),
|
||||
// Lower the anonymous structs or unions in a nested lowering context.
|
||||
//
|
||||
// ```
|
||||
@ -1504,6 +1504,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
);
|
||||
hir::TyKind::Err(guar)
|
||||
}
|
||||
TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),
|
||||
};
|
||||
|
||||
hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
|
||||
|
@ -881,7 +881,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
&item.vis,
|
||||
errors::VisibilityNotPermittedNote::TraitImpl,
|
||||
);
|
||||
if let TyKind::Err = self_ty.kind {
|
||||
// njn: use Dummy here
|
||||
if let TyKind::Err(_) = self_ty.kind {
|
||||
this.dcx().emit_err(errors::ObsoleteAuto { span: item.span });
|
||||
}
|
||||
if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
|
||||
|
@ -1048,11 +1048,16 @@ impl<'a> State<'a> {
|
||||
ast::TyKind::Infer => {
|
||||
self.word("_");
|
||||
}
|
||||
ast::TyKind::Err => {
|
||||
ast::TyKind::Err(_) => {
|
||||
self.popen();
|
||||
self.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
}
|
||||
ast::TyKind::Dummy => {
|
||||
self.popen();
|
||||
self.word("/*DUMMY*/");
|
||||
self.pclose();
|
||||
}
|
||||
ast::TyKind::ImplicitSelf => {
|
||||
self.word("Self");
|
||||
}
|
||||
|
@ -567,10 +567,13 @@ impl DummyResult {
|
||||
}
|
||||
|
||||
/// A plain dummy type.
|
||||
pub fn raw_ty(sp: Span, is_error: bool) -> P<ast::Ty> {
|
||||
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
|
||||
// FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some
|
||||
// values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not
|
||||
// support, so we use an empty tuple instead.
|
||||
P(ast::Ty {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(ThinVec::new()) },
|
||||
kind: ast::TyKind::Tup(ThinVec::new()),
|
||||
span: sp,
|
||||
tokens: None,
|
||||
})
|
||||
@ -611,7 +614,7 @@ impl MacResult for DummyResult {
|
||||
}
|
||||
|
||||
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
|
||||
Some(DummyResult::raw_ty(self.span, self.is_error))
|
||||
Some(DummyResult::raw_ty(self.span))
|
||||
}
|
||||
|
||||
fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> {
|
||||
|
@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
CoerceMany::with_coercion_sites(coerce_first, arms)
|
||||
};
|
||||
|
||||
let mut other_arms = vec![]; // Used only for diagnostics.
|
||||
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
|
||||
let mut prior_arm = None;
|
||||
for arm in arms {
|
||||
if let Some(e) = &arm.guard {
|
||||
@ -118,9 +118,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
prior_arm_ty,
|
||||
prior_arm_span,
|
||||
scrut_span: scrut.span,
|
||||
scrut_hir_id: scrut.hir_id,
|
||||
source: match_src,
|
||||
prior_arms: other_arms.clone(),
|
||||
prior_non_diverging_arms: prior_non_diverging_arms.clone(),
|
||||
opt_suggest_box_span,
|
||||
})),
|
||||
),
|
||||
@ -142,16 +141,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
false,
|
||||
);
|
||||
|
||||
other_arms.push(arm_span);
|
||||
if other_arms.len() > 5 {
|
||||
other_arms.remove(0);
|
||||
}
|
||||
|
||||
if !arm_ty.is_never() {
|
||||
// When a match arm has type `!`, then it doesn't influence the expected type for
|
||||
// the following arm. If all of the prior arms are `!`, then the influence comes
|
||||
// from elsewhere and we shouldn't point to any previous arm.
|
||||
prior_arm = Some((arm_block_id, arm_ty, arm_span));
|
||||
|
||||
prior_non_diverging_arms.push(arm_span);
|
||||
if prior_non_diverging_arms.len() > 5 {
|
||||
prior_non_diverging_arms.remove(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,10 +777,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
prior_arm_span,
|
||||
prior_arm_ty,
|
||||
source,
|
||||
ref prior_arms,
|
||||
ref prior_non_diverging_arms,
|
||||
opt_suggest_box_span,
|
||||
scrut_span,
|
||||
scrut_hir_id,
|
||||
..
|
||||
}) => match source {
|
||||
hir::MatchSource::TryDesugar(scrut_hir_id) => {
|
||||
@ -817,12 +816,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
});
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
let mut any_multiline_arm = source_map.is_multiline(arm_span);
|
||||
if prior_arms.len() <= 4 {
|
||||
for sp in prior_arms {
|
||||
if prior_non_diverging_arms.len() <= 4 {
|
||||
for sp in prior_non_diverging_arms {
|
||||
any_multiline_arm |= source_map.is_multiline(*sp);
|
||||
err.span_label(*sp, format!("this is found to be of type `{t}`"));
|
||||
}
|
||||
} else if let Some(sp) = prior_arms.last() {
|
||||
} else if let Some(sp) = prior_non_diverging_arms.last() {
|
||||
any_multiline_arm |= source_map.is_multiline(*sp);
|
||||
err.span_label(
|
||||
*sp,
|
||||
@ -848,24 +847,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
) {
|
||||
err.subdiagnostic(subdiag);
|
||||
}
|
||||
if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id)
|
||||
&& let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id)
|
||||
&& let hir::StmtKind::Expr(_) = stmt.kind
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
stmt.span.shrink_to_hi(),
|
||||
"consider using a semicolon here, but this will discard any values \
|
||||
in the match arms",
|
||||
";",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
if let Some(ret_sp) = opt_suggest_box_span {
|
||||
// Get return type span and point to it.
|
||||
self.suggest_boxing_for_return_impl_trait(
|
||||
err,
|
||||
ret_sp,
|
||||
prior_arms.iter().chain(std::iter::once(&arm_span)).copied(),
|
||||
prior_non_diverging_arms
|
||||
.iter()
|
||||
.chain(std::iter::once(&arm_span))
|
||||
.copied(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -203,10 +203,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
})
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||
prior_arms,
|
||||
prior_non_diverging_arms,
|
||||
..
|
||||
}) => {
|
||||
if let [.., arm_span] = &prior_arms[..] {
|
||||
if let [.., arm_span] = &prior_non_diverging_arms[..] {
|
||||
Some(ConsiderAddingAwait::BothFuturesSugg {
|
||||
first: arm_span.shrink_to_hi(),
|
||||
second: exp_span.shrink_to_hi(),
|
||||
@ -234,11 +234,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||
ref prior_arms,
|
||||
ref prior_non_diverging_arms,
|
||||
..
|
||||
}) => Some({
|
||||
ConsiderAddingAwait::FutureSuggMultiple {
|
||||
spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
|
||||
spans: prior_non_diverging_arms
|
||||
.iter()
|
||||
.map(|arm| arm.shrink_to_hi())
|
||||
.collect(),
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
|
@ -569,9 +569,8 @@ pub struct MatchExpressionArmCause<'tcx> {
|
||||
pub prior_arm_ty: Ty<'tcx>,
|
||||
pub prior_arm_span: Span,
|
||||
pub scrut_span: Span,
|
||||
pub scrut_hir_id: hir::HirId,
|
||||
pub source: hir::MatchSource,
|
||||
pub prior_arms: Vec<Span>,
|
||||
pub prior_non_diverging_arms: Vec<Span>,
|
||||
pub opt_suggest_box_span: Option<Span>,
|
||||
}
|
||||
|
||||
|
@ -2363,28 +2363,42 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
|
||||
/// When we create a closure, we record its kind (i.e., what trait
|
||||
/// it implements) into its `ClosureArgs` using a type
|
||||
/// it implements, constrained by how it uses its borrows) into its
|
||||
/// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type
|
||||
/// parameter. This is kind of a phantom type, except that the
|
||||
/// most convenient thing for us to are the integral types. This
|
||||
/// function converts such a special type into the closure
|
||||
/// kind. To go the other way, use `closure_kind.to_ty(tcx)`.
|
||||
/// kind. To go the other way, use [`Ty::from_closure_kind`].
|
||||
///
|
||||
/// Note that during type checking, we use an inference variable
|
||||
/// to represent the closure kind, because it has not yet been
|
||||
/// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`)
|
||||
/// is complete, that type variable will be unified.
|
||||
///
|
||||
/// To be noted that you can use [`ClosureArgs::kind()`] or [`CoroutineClosureArgs::kind()`]
|
||||
/// to get the same information, which you can get by calling [`GenericArgs::as_closure()`]
|
||||
/// or [`GenericArgs::as_coroutine_closure()`], depending on the type of the closure.
|
||||
///
|
||||
/// Otherwise, this method can be used as follows:
|
||||
/// is complete, that type variable will be unified with one of
|
||||
/// the integral types.
|
||||
///
|
||||
/// ```rust,ignore (snippet of compiler code)
|
||||
/// let TyKind::Closure(def_id, [closure_fn_kind_ty, ..]) = closure_ty.kind()
|
||||
/// && let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind()
|
||||
/// if let TyKind::Closure(def_id, args) = closure_ty.kind()
|
||||
/// && let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
|
||||
/// {
|
||||
/// // your code
|
||||
/// println!("{closure_kind:?}");
|
||||
/// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind()
|
||||
/// && let Some(closure_kind) = args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
|
||||
/// {
|
||||
/// println!("{closure_kind:?}");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// After upvar analysis, you should instead use [`ClosureArgs::kind()`]
|
||||
/// or [`CoroutineClosureArgs::kind()`] to assert that the `ClosureKind`
|
||||
/// has been constrained instead of manually calling this method.
|
||||
///
|
||||
/// ```rust,ignore (snippet of compiler code)
|
||||
/// if let TyKind::Closure(def_id, args) = closure_ty.kind()
|
||||
/// {
|
||||
/// println!("{:?}", args.as_closure().kind());
|
||||
/// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind()
|
||||
/// {
|
||||
/// println!("{:?}", args.as_coroutine_closure().kind());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
|
||||
@ -2406,7 +2420,8 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Inverse of [`Ty::to_opt_closure_kind`].
|
||||
/// Inverse of [`Ty::to_opt_closure_kind`]. See docs on that method
|
||||
/// for explanation of the relationship between `Ty` and [`ty::ClosureKind`].
|
||||
pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
|
||||
match kind {
|
||||
ty::ClosureKind::Fn => tcx.types.i8,
|
||||
|
@ -653,7 +653,6 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
||||
debug!("about to call mir_drops_elaborated...");
|
||||
let body = tcx.mir_drops_elaborated_and_const_checked(did).steal();
|
||||
let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
|
||||
debug!("body: {:#?}", body);
|
||||
|
||||
if body.tainted_by_errors.is_some() {
|
||||
return body;
|
||||
|
@ -15,7 +15,8 @@ impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
|
||||
}
|
||||
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
debug!("remove_noop_landing_pads({:?})", body);
|
||||
let def_id = body.source.def_id();
|
||||
debug!(?def_id);
|
||||
self.remove_nop_landing_pads(body)
|
||||
}
|
||||
}
|
||||
@ -81,8 +82,6 @@ impl RemoveNoopLandingPads {
|
||||
}
|
||||
|
||||
fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
|
||||
debug!("body: {:#?}", body);
|
||||
|
||||
// Skip the pass if there are no blocks with a resume terminator.
|
||||
let has_resume = body
|
||||
.basic_blocks
|
||||
|
@ -46,14 +46,14 @@ use std::ops::{Deref, DerefMut};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
/// Creates a placeholder argument.
|
||||
pub(super) fn dummy_arg(ident: Ident) -> Param {
|
||||
pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
|
||||
let pat = P(Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingAnnotation::NONE, ident, None),
|
||||
span: ident.span,
|
||||
tokens: None,
|
||||
});
|
||||
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
|
||||
let ty = Ty { kind: TyKind::Err(guar), span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
|
||||
Param {
|
||||
attrs: AttrVec::default(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -1540,14 +1540,14 @@ impl<'a> Parser<'a> {
|
||||
pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
|
||||
if self.token == token::Question {
|
||||
self.bump();
|
||||
self.dcx().emit_err(QuestionMarkInType {
|
||||
let guar = self.dcx().emit_err(QuestionMarkInType {
|
||||
span: self.prev_token.span,
|
||||
sugg: QuestionMarkInTypeSugg {
|
||||
left: ty.span.shrink_to_lo(),
|
||||
right: self.prev_token.span,
|
||||
},
|
||||
});
|
||||
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
|
||||
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err(guar))
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
@ -2304,8 +2304,8 @@ impl<'a> Parser<'a> {
|
||||
|
||||
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
|
||||
let span = param.pat.span;
|
||||
param.ty.kind = TyKind::Err;
|
||||
self.dcx().emit_err(SelfParamNotFirst { span });
|
||||
let guar = self.dcx().emit_err(SelfParamNotFirst { span });
|
||||
param.ty.kind = TyKind::Err(guar);
|
||||
Ok(param)
|
||||
}
|
||||
|
||||
@ -2437,7 +2437,7 @@ impl<'a> Parser<'a> {
|
||||
pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut ThinVec<Param>) {
|
||||
let mut seen_inputs = FxHashSet::default();
|
||||
for input in fn_inputs.iter_mut() {
|
||||
let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) =
|
||||
let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err(_)) =
|
||||
(&input.pat.kind, &input.ty.kind)
|
||||
{
|
||||
Some(*ident)
|
||||
@ -2644,8 +2644,10 @@ impl<'a> Parser<'a> {
|
||||
"::",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.emit();
|
||||
return Ok(GenericArg::Type(self.mk_ty(start.to(expr.span), TyKind::Err)));
|
||||
let guar = err.emit();
|
||||
return Ok(GenericArg::Type(
|
||||
self.mk_ty(start.to(expr.span), TyKind::Err(guar)),
|
||||
));
|
||||
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
|
||||
{
|
||||
// Avoid the following output by checking that we consumed a full const arg:
|
||||
|
@ -591,7 +591,23 @@ impl<'a> Parser<'a> {
|
||||
let ty_second = if self.token == token::DotDot {
|
||||
// We need to report this error after `cfg` expansion for compatibility reasons
|
||||
self.bump(); // `..`, do not add it to expected tokens
|
||||
Some(self.mk_ty(self.prev_token.span, TyKind::Err))
|
||||
|
||||
// FIXME(nnethercote): AST validation later detects this
|
||||
// `TyKind::Err` and emits an errors. So why the unchecked
|
||||
// ErrorGuaranteed?
|
||||
// - A `span_delayed_bug` doesn't work here, because rustfmt can
|
||||
// hit this path but then not hit the follow-up path in the AST
|
||||
// validator that issues the error, which results in ICEs.
|
||||
// - `TyKind::Dummy` doesn't work, because it ends up reaching HIR
|
||||
// lowering, which results in ICEs. Changing `TyKind::Dummy` to
|
||||
// `TyKind::Err` during AST validation might fix that, but that's
|
||||
// not possible because AST validation doesn't allow mutability.
|
||||
//
|
||||
// #121072 will hopefully remove all this special handling of the
|
||||
// obsolete `impl Trait for ..` and then this can go away.
|
||||
#[allow(deprecated)]
|
||||
let guar = rustc_errors::ErrorGuaranteed::unchecked_error_guaranteed();
|
||||
Some(self.mk_ty(self.prev_token.span, TyKind::Err(guar)))
|
||||
} else if has_for || self.token.can_begin_type() {
|
||||
Some(self.parse_ty()?)
|
||||
} else {
|
||||
@ -2628,13 +2644,13 @@ impl<'a> Parser<'a> {
|
||||
p.recover_diff_marker();
|
||||
let snapshot = p.create_snapshot_for_diagnostic();
|
||||
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
|
||||
e.emit();
|
||||
let guar = e.emit();
|
||||
let lo = p.prev_token.span;
|
||||
p.restore_snapshot(snapshot);
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(Delimiter::Parenthesis)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span))))
|
||||
Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)), guar))
|
||||
});
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
first_param = false;
|
||||
@ -2671,8 +2687,8 @@ impl<'a> Parser<'a> {
|
||||
return if let Some(ident) =
|
||||
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
|
||||
{
|
||||
err.emit();
|
||||
Ok((dummy_arg(ident), TrailingToken::None))
|
||||
let guar = err.emit();
|
||||
Ok((dummy_arg(ident, guar), TrailingToken::None))
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
|
@ -678,8 +678,9 @@ impl<'a> Parser<'a> {
|
||||
c.into()
|
||||
}
|
||||
Some(GenericArg::Lifetime(lt)) => {
|
||||
self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
|
||||
self.mk_ty(span, ast::TyKind::Err).into()
|
||||
let guar =
|
||||
self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
|
||||
self.mk_ty(span, ast::TyKind::Err(guar)).into()
|
||||
}
|
||||
None => {
|
||||
let after_eq = eq.shrink_to_hi();
|
||||
@ -779,7 +780,7 @@ impl<'a> Parser<'a> {
|
||||
// type to determine if error recovery has occurred and if the input is not a
|
||||
// syntactically valid type after all.
|
||||
if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
|
||||
&& let ast::TyKind::Err = inner_ty.kind
|
||||
&& let ast::TyKind::Err(_) = inner_ty.kind
|
||||
&& let Some(snapshot) = snapshot
|
||||
&& let Some(expr) =
|
||||
self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
|
||||
|
@ -346,8 +346,10 @@ impl<'a> Parser<'a> {
|
||||
AllowCVariadic::No => {
|
||||
// FIXME(Centril): Should we just allow `...` syntactically
|
||||
// anywhere in a type and use semantic restrictions instead?
|
||||
self.dcx().emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
|
||||
TyKind::Err
|
||||
let guar = self
|
||||
.dcx()
|
||||
.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
|
||||
TyKind::Err(guar)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -493,8 +495,8 @@ impl<'a> Parser<'a> {
|
||||
{
|
||||
// Recover from `[LIT; EXPR]` and `[LIT]`
|
||||
self.bump();
|
||||
err.emit();
|
||||
self.mk_ty(self.prev_token.span, TyKind::Err)
|
||||
let guar = err.emit();
|
||||
self.mk_ty(self.prev_token.span, TyKind::Err(guar))
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
@ -616,8 +616,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
||||
Infer,
|
||||
ImplicitSelf,
|
||||
MacCall,
|
||||
Err,
|
||||
CVarArgs
|
||||
CVarArgs,
|
||||
Dummy,
|
||||
Err
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -86,7 +86,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||
|
||||
const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||
// tidy-alphabetical-start
|
||||
// FEAT_AES
|
||||
// FEAT_AES & FEAT_PMULL
|
||||
("aes", Stable),
|
||||
// FEAT_BF16
|
||||
("bf16", Stable),
|
||||
@ -124,7 +124,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||
("lor", Stable),
|
||||
// FEAT_LSE
|
||||
("lse", Stable),
|
||||
// FEAT_MTE
|
||||
// FEAT_MTE & FEAT_MTE2
|
||||
("mte", Stable),
|
||||
// FEAT_AdvSimd & FEAT_FP
|
||||
("neon", Stable),
|
||||
@ -138,7 +138,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||
("pmuv3", Stable),
|
||||
// FEAT_RAND
|
||||
("rand", Stable),
|
||||
// FEAT_RAS
|
||||
// FEAT_RAS & FEAT_RASv1p1
|
||||
("ras", Stable),
|
||||
// FEAT_RCPC
|
||||
("rcpc", Stable),
|
||||
@ -156,7 +156,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
||||
("sm4", Stable),
|
||||
// FEAT_SPE
|
||||
("spe", Stable),
|
||||
// FEAT_SSBS
|
||||
// FEAT_SSBS & FEAT_SSBS2
|
||||
("ssbs", Stable),
|
||||
// FEAT_SVE
|
||||
("sve", Stable),
|
||||
|
@ -8,14 +8,16 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
|
||||
*[other] arguments
|
||||
}
|
||||
|
||||
trait_selection_closure_fn_mut_label = closure is `FnMut` because it mutates the variable `{$place}` here
|
||||
trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment
|
||||
|
||||
trait_selection_closure_fn_once_label = closure is `FnOnce` because it moves the variable `{$place}` out of its environment
|
||||
trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here
|
||||
|
||||
trait_selection_closure_kind_mismatch = expected a closure that implements the `{$expected}` trait, but this closure only implements `{$found}`
|
||||
.label = this closure implements `{$found}`, not `{$expected}`
|
||||
trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment
|
||||
|
||||
trait_selection_closure_kind_requirement = the requirement to implement `{$expected}` derives from here
|
||||
trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}`
|
||||
.label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}`
|
||||
|
||||
trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here
|
||||
|
||||
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
|
||||
|
||||
|
@ -135,6 +135,8 @@ pub struct ClosureKindMismatch {
|
||||
#[label(trait_selection_closure_kind_requirement)]
|
||||
pub cause_span: Span,
|
||||
|
||||
pub trait_prefix: &'static str,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub fn_once_label: Option<ClosureFnOnceLabel>,
|
||||
|
||||
@ -157,3 +159,11 @@ pub struct ClosureFnMutLabel {
|
||||
pub span: Span,
|
||||
pub place: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(trait_selection_async_closure_not_fn)]
|
||||
pub(crate) struct AsyncClosureNotFn {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: &'static str,
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
|
||||
use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _};
|
||||
use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
|
||||
use crate::errors::{
|
||||
AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
|
||||
};
|
||||
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
||||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::infer::InferCtxtExt as _;
|
||||
@ -959,34 +961,102 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
fn emit_specialized_closure_kind_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
mut trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
let self_ty = trait_ref.self_ty().skip_binder();
|
||||
if let ty::Closure(closure_def_id, closure_args) = *self_ty.kind()
|
||||
&& let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id())
|
||||
&& let Some(found_kind) = self.closure_kind(self_ty)
|
||||
// If `AsyncFnKindHelper` is not implemented, that means that the closure kind
|
||||
// doesn't extend the goal kind. This is worth reporting, but we can only do so
|
||||
// if we actually know which closure this goal comes from, so look at the cause
|
||||
// to see if we can extract that information.
|
||||
if Some(trait_ref.def_id()) == self.tcx.lang_items().async_fn_kind_helper()
|
||||
&& let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind()
|
||||
&& let Some(expected_kind) =
|
||||
trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
|
||||
&& !found_kind.extends(expected_kind)
|
||||
&& let sig = closure_args.as_closure().sig()
|
||||
&& self.can_sub(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
sig.map_bound(|sig| {
|
||||
ty::TraitRef::new(
|
||||
self.tcx,
|
||||
trait_ref.def_id(),
|
||||
[trait_ref.self_ty().skip_binder(), sig.inputs()[0]],
|
||||
)
|
||||
}),
|
||||
)
|
||||
{
|
||||
let mut err =
|
||||
self.report_closure_error(&obligation, closure_def_id, found_kind, expected_kind);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
Some(err.emit())
|
||||
} else {
|
||||
None
|
||||
if let Some((_, Some(parent))) = obligation.cause.code().parent() {
|
||||
// If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
|
||||
trait_ref = parent.to_poly_trait_ref();
|
||||
} else if let &ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
&& let Some(typeck_results) = &self.typeck_results
|
||||
&& let ty::Closure(closure_def_id, _) | ty::CoroutineClosure(closure_def_id, _) =
|
||||
*typeck_results.node_type(arg_hir_id).kind()
|
||||
{
|
||||
// Otherwise, extract the closure kind from the obligation.
|
||||
let mut err = self.report_closure_error(
|
||||
&obligation,
|
||||
closure_def_id,
|
||||
found_kind,
|
||||
expected_kind,
|
||||
"async ",
|
||||
);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
return Some(err.emit());
|
||||
}
|
||||
}
|
||||
|
||||
let self_ty = trait_ref.self_ty().skip_binder();
|
||||
|
||||
if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) {
|
||||
let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() {
|
||||
ty::Closure(def_id, args) => {
|
||||
(def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None)
|
||||
}
|
||||
ty::CoroutineClosure(def_id, args) => (
|
||||
def_id,
|
||||
args.as_coroutine_closure()
|
||||
.coroutine_closure_sig()
|
||||
.map_bound(|sig| sig.tupled_inputs_ty),
|
||||
Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
|
||||
),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let expected_args = trait_ref.map_bound(|trait_ref| trait_ref.args.type_at(1));
|
||||
|
||||
// Verify that the arguments are compatible. If the signature is
|
||||
// mismatched, then we have a totally different error to report.
|
||||
if self.enter_forall(found_args, |found_args| {
|
||||
self.enter_forall(expected_args, |expected_args| {
|
||||
!self.can_sub(obligation.param_env, expected_args, found_args)
|
||||
})
|
||||
}) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(found_kind) = self.closure_kind(self_ty)
|
||||
&& !found_kind.extends(expected_kind)
|
||||
{
|
||||
let mut err = self.report_closure_error(
|
||||
&obligation,
|
||||
closure_def_id,
|
||||
found_kind,
|
||||
expected_kind,
|
||||
"",
|
||||
);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
return Some(err.emit());
|
||||
}
|
||||
|
||||
// If the closure has captures, then perhaps the reason that the trait
|
||||
// is unimplemented is because async closures don't implement `Fn`/`FnMut`
|
||||
// if they have captures.
|
||||
if let Some(by_ref_captures) = by_ref_captures
|
||||
&& let ty::FnPtr(sig) = by_ref_captures.kind()
|
||||
&& !sig.skip_binder().output().is_unit()
|
||||
{
|
||||
let mut err = self.tcx.dcx().create_err(AsyncClosureNotFn {
|
||||
span: self.tcx.def_span(closure_def_id),
|
||||
kind: expected_kind.as_str(),
|
||||
});
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
return Some(err.emit());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn fn_arg_obligation(
|
||||
@ -1493,6 +1563,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
|
||||
closure_def_id: DefId,
|
||||
found_kind: ty::ClosureKind,
|
||||
kind: ty::ClosureKind,
|
||||
trait_prefix: &'static str,
|
||||
) -> DiagnosticBuilder<'tcx>;
|
||||
|
||||
fn report_cyclic_signature_error(
|
||||
@ -3376,6 +3447,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
closure_def_id: DefId,
|
||||
found_kind: ty::ClosureKind,
|
||||
kind: ty::ClosureKind,
|
||||
trait_prefix: &'static str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let closure_span = self.tcx.def_span(closure_def_id);
|
||||
|
||||
@ -3384,6 +3456,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
expected: kind,
|
||||
found: found_kind,
|
||||
cause_span: obligation.cause.span,
|
||||
trait_prefix,
|
||||
fn_once_label: None,
|
||||
fn_mut_label: None,
|
||||
};
|
||||
|
@ -472,6 +472,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")]
|
||||
@ -552,6 +554,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")]
|
||||
@ -606,6 +610,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")]
|
||||
@ -686,6 +692,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")]
|
||||
@ -740,6 +748,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ``` should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")]
|
||||
@ -831,11 +841,15 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")]
|
||||
@ -901,11 +915,15 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")]
|
||||
@ -970,11 +988,15 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")]
|
||||
@ -1039,11 +1061,15 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")]
|
||||
@ -1121,6 +1147,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")]
|
||||
@ -1175,6 +1203,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")]
|
||||
@ -1256,6 +1286,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")]
|
||||
@ -1340,6 +1372,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")]
|
||||
@ -1414,6 +1448,8 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")]
|
||||
|
@ -480,6 +480,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")]
|
||||
@ -561,6 +563,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panic because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")]
|
||||
@ -620,6 +624,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")]
|
||||
@ -700,6 +706,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ``` should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")]
|
||||
@ -785,6 +793,13 @@ macro_rules! uint_impl {
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -840,6 +855,12 @@ macro_rules! uint_impl {
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")]
|
||||
/// ```
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -895,6 +916,13 @@ macro_rules! uint_impl {
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -951,6 +979,13 @@ macro_rules! uint_impl {
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of division by zero:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -1172,6 +1207,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")]
|
||||
@ -1226,6 +1263,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")]
|
||||
@ -1307,6 +1346,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")]
|
||||
@ -1406,6 +1447,8 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")]
|
||||
/// ```
|
||||
///
|
||||
/// The following panics because of overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(strict_overflow_ops)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")]
|
||||
|
@ -161,7 +161,7 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
||||
// first E0 A0 80 last EF BF BF
|
||||
// excluding surrogates codepoints \u{d800} to \u{dfff}
|
||||
// ED A0 80 to ED BF BF
|
||||
// 4-byte encoding is for codepoints \u{1000}0 to \u{10ff}ff
|
||||
// 4-byte encoding is for codepoints \u{10000} to \u{10ffff}
|
||||
// first F0 90 80 80 last F4 8F BF BF
|
||||
//
|
||||
// Use the UTF-8 syntax from the RFC
|
||||
|
@ -99,21 +99,21 @@ fn skip_search<const SOR: usize, const OFFSETS: usize>(
|
||||
offset_idx % 2 == 1
|
||||
}
|
||||
|
||||
pub const UNICODE_VERSION: (u8, u8, u8) = (15, 0, 0);
|
||||
pub const UNICODE_VERSION: (u8, u8, u8) = (15, 1, 0);
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub mod alphabetic {
|
||||
static SHORT_OFFSET_RUNS: [u32; 53] = [
|
||||
static SHORT_OFFSET_RUNS: [u32; 54] = [
|
||||
706, 33559113, 872420973, 952114966, 1161831606, 1310731264, 1314926597, 1394619392,
|
||||
1444957632, 1447077005, 1451271693, 1459672996, 1648425216, 1658911342, 1661009214,
|
||||
1707147904, 1793132343, 1887506048, 2040601600, 2392923872, 2481005466, 2504077200,
|
||||
2514564144, 2520859648, 2527151687, 2529257472, 2531355193, 2533453376, 2564917240,
|
||||
2596375766, 2600579056, 2606870819, 2621551356, 2642525184, 2644628480, 2665600678,
|
||||
2743197440, 2791432848, 2841765072, 2850154464, 2854350336, 2887905584, 3026321408,
|
||||
3038947040, 3041048378, 3045248674, 3053644769, 3057842176, 3059939870, 3062038528,
|
||||
3064140619, 3066241968, 3071550384,
|
||||
3038947040, 3041048378, 3045248674, 3053644769, 3057839710, 3062036480, 3064134174,
|
||||
3066232832, 3068334923, 3070436272, 3075744688,
|
||||
];
|
||||
static OFFSETS: [u8; 1465] = [
|
||||
static OFFSETS: [u8; 1467] = [
|
||||
65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42,
|
||||
5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39,
|
||||
14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10,
|
||||
@ -167,7 +167,7 @@ pub mod alphabetic {
|
||||
1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1,
|
||||
1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2,
|
||||
4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32,
|
||||
0, 6, 222, 2, 0, 14, 0, 0, 0, 0, 0, 5, 0, 0,
|
||||
0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0,
|
||||
];
|
||||
pub fn lookup(c: char) -> bool {
|
||||
super::skip_search(
|
||||
|
@ -40,6 +40,9 @@ use crate::lint::init_lints;
|
||||
pub(crate) struct GlobalTestOptions {
|
||||
/// Whether to disable the default `extern crate my_crate;` when creating doctests.
|
||||
pub(crate) no_crate_inject: bool,
|
||||
/// Whether inserting extra indent spaces in code block,
|
||||
/// default is `false`, only `true` for generating code link of Rust playground
|
||||
pub(crate) insert_indent_space: bool,
|
||||
/// Additional crate-level attributes to add to doctests.
|
||||
pub(crate) attrs: Vec<String>,
|
||||
}
|
||||
@ -221,7 +224,8 @@ pub(crate) fn run_tests(
|
||||
fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
||||
let mut opts = GlobalTestOptions { no_crate_inject: false, attrs: Vec::new() };
|
||||
let mut opts =
|
||||
GlobalTestOptions { no_crate_inject: false, attrs: Vec::new(), insert_indent_space: false };
|
||||
|
||||
let test_attrs: Vec<_> = attrs
|
||||
.iter()
|
||||
@ -725,7 +729,17 @@ pub(crate) fn make_test(
|
||||
// /// ``` <- end of the inner main
|
||||
line_offset += 1;
|
||||
|
||||
prog.extend([&main_pre, everything_else, &main_post].iter().cloned());
|
||||
// add extra 4 spaces for each line to offset the code block
|
||||
let content = if opts.insert_indent_space {
|
||||
everything_else
|
||||
.lines()
|
||||
.map(|line| format!(" {}", line))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
} else {
|
||||
everything_else.to_string()
|
||||
};
|
||||
prog.extend([&main_pre, content.as_str(), &main_post].iter().cloned());
|
||||
}
|
||||
|
||||
debug!("final doctest:\n{prog}");
|
||||
|
@ -53,7 +53,8 @@ assert_eq!(2+2, 4);
|
||||
fn make_test_no_crate_inject() {
|
||||
// Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
|
||||
// adding it anyway.
|
||||
let opts = GlobalTestOptions { no_crate_inject: true, attrs: vec![] };
|
||||
let opts =
|
||||
GlobalTestOptions { no_crate_inject: true, attrs: vec![], insert_indent_space: false };
|
||||
let input = "use asdf::qwop;
|
||||
assert_eq!(2+2, 4);";
|
||||
let expected = "#![allow(unused)]
|
||||
@ -302,3 +303,44 @@ assert_eq!(2+2, 4);
|
||||
make_test(input, None, false, &opts, DEFAULT_EDITION, Some("_some_unique_name"));
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_test_insert_extra_space() {
|
||||
// will insert indent spaces in the code block if `insert_indent_space` is true
|
||||
let opts =
|
||||
GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true };
|
||||
let input = "use std::*;
|
||||
assert_eq!(2+2, 4);
|
||||
eprintln!(\"hello anan\");
|
||||
";
|
||||
let expected = "#![allow(unused)]
|
||||
fn main() {
|
||||
use std::*;
|
||||
assert_eq!(2+2, 4);
|
||||
eprintln!(\"hello anan\");
|
||||
}"
|
||||
.to_string();
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_test_insert_extra_space_fn_main() {
|
||||
// if input already has a fn main, it should insert a space before it
|
||||
let opts =
|
||||
GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true };
|
||||
let input = "use std::*;
|
||||
fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
eprintln!(\"hello anan\");
|
||||
}";
|
||||
let expected = "#![allow(unused)]
|
||||
use std::*;
|
||||
fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
eprintln!(\"hello anan\");
|
||||
}"
|
||||
.to_string();
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None);
|
||||
assert_eq!((output, len), (expected, 1));
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ use std::str::{self, CharIndices};
|
||||
|
||||
use crate::clean::RenderedLink;
|
||||
use crate::doctest;
|
||||
use crate::doctest::GlobalTestOptions;
|
||||
use crate::html::escape::Escape;
|
||||
use crate::html::format::Buffer;
|
||||
use crate::html::highlight;
|
||||
@ -302,8 +303,10 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
.intersperse("\n".into())
|
||||
.collect::<String>();
|
||||
let krate = krate.as_ref().map(|s| s.as_str());
|
||||
let (test, _, _) =
|
||||
doctest::make_test(&test, krate, false, &Default::default(), edition, None);
|
||||
|
||||
let mut opts: GlobalTestOptions = Default::default();
|
||||
opts.insert_indent_space = true;
|
||||
let (test, _, _) = doctest::make_test(&test, krate, false, &opts, edition, None);
|
||||
let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" };
|
||||
|
||||
let test_escaped = small_url_encode(test);
|
||||
|
@ -690,7 +690,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
|
||||
match (&l.kind, &r.kind) {
|
||||
(Paren(l), _) => eq_ty(l, r),
|
||||
(_, Paren(r)) => eq_ty(l, r),
|
||||
(Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err, Err) | (CVarArgs, CVarArgs) => true,
|
||||
(Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err(_), Err(_)) | (CVarArgs, CVarArgs) => true,
|
||||
(Slice(l), Slice(r)) => eq_ty(l, r),
|
||||
(Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value),
|
||||
(Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty),
|
||||
|
@ -859,7 +859,7 @@ impl Rewrite for ast::Ty {
|
||||
})
|
||||
}
|
||||
ast::TyKind::CVarArgs => Some("...".to_owned()),
|
||||
ast::TyKind::Err => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::Dummy | ast::TyKind::Err(_) => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::Typeof(ref anon_const) => rewrite_call(
|
||||
context,
|
||||
"typeof",
|
||||
|
@ -10,4 +10,4 @@
|
||||
pub fn dummy() {}
|
||||
|
||||
// ensure that `extern crate foo;` was inserted into code snips automatically:
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run"
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0A++++use+foo::dummy;%0A++++dummy();%0A%7D&edition=2015"]' "Run"
|
||||
|
@ -22,6 +22,6 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0Aprintln!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
|
||||
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "Run"
|
||||
|
15
tests/ui/async-await/async-closures/not-fn.rs
Normal file
15
tests/ui/async-await/async-closures/not-fn.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// edition:2021
|
||||
|
||||
// FIXME(async_closures): This needs a better error message!
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {
|
||||
fn needs_fn<T>(_: impl FnMut() -> T) {}
|
||||
|
||||
let mut x = 1;
|
||||
needs_fn(async || {
|
||||
//~^ ERROR async closure does not implement `FnMut` because it captures state from its environment
|
||||
x += 1;
|
||||
});
|
||||
}
|
16
tests/ui/async-await/async-closures/not-fn.stderr
Normal file
16
tests/ui/async-await/async-closures/not-fn.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: async closure does not implement `FnMut` because it captures state from its environment
|
||||
--> $DIR/not-fn.rs:11:14
|
||||
|
|
||||
LL | needs_fn(async || {
|
||||
| -------- ^^^^^^^^
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `needs_fn`
|
||||
--> $DIR/not-fn.rs:8:28
|
||||
|
|
||||
LL | fn needs_fn<T>(_: impl FnMut() -> T) {}
|
||||
| ^^^^^^^^^^^^ required by this bound in `needs_fn`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -9,8 +9,7 @@ fn main() {
|
||||
|
||||
let mut x = 1;
|
||||
needs_async_fn(async || {
|
||||
//~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>
|
||||
// FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth.
|
||||
//~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
|
||||
x += 1;
|
||||
});
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not satisfied
|
||||
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut`
|
||||
--> $DIR/wrong-fn-kind.rs:11:20
|
||||
|
|
||||
LL | needs_async_fn(async || {
|
||||
| _____--------------_^
|
||||
| -------------- -^^^^^^^
|
||||
| | |
|
||||
| _____|______________this closure implements `async FnMut`, not `async Fn`
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | |
|
||||
LL | | // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth.
|
||||
LL | | x += 1;
|
||||
| | - closure is `async FnMut` because it mutates the variable `x` here
|
||||
LL | | });
|
||||
| |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not implemented for `i16`
|
||||
| |_____- the requirement to implement `async Fn` derives from here
|
||||
|
|
||||
note: required by a bound in `needs_async_fn`
|
||||
--> $DIR/wrong-fn-kind.rs:8:31
|
||||
@ -19,4 +21,4 @@ LL | fn needs_async_fn(_: impl async Fn()) {}
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0525`.
|
||||
|
17
tests/ui/match/dont-highlight-diverging-arms.rs
Normal file
17
tests/ui/match/dont-highlight-diverging-arms.rs
Normal file
@ -0,0 +1,17 @@
|
||||
fn main() {
|
||||
let m = 42u32;
|
||||
|
||||
let value = 'out: {
|
||||
match m {
|
||||
1 => break 'out Some(1u16),
|
||||
2 => Some(2u16),
|
||||
3 => break 'out Some(3u16),
|
||||
4 => break 'out Some(4u16),
|
||||
5 => break 'out Some(5u16),
|
||||
_ => {}
|
||||
//~^ ERROR `match` arms have incompatible types
|
||||
}
|
||||
|
||||
None
|
||||
};
|
||||
}
|
21
tests/ui/match/dont-highlight-diverging-arms.stderr
Normal file
21
tests/ui/match/dont-highlight-diverging-arms.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/dont-highlight-diverging-arms.rs:11:18
|
||||
|
|
||||
LL | / match m {
|
||||
LL | | 1 => break 'out Some(1u16),
|
||||
LL | | 2 => Some(2u16),
|
||||
| | ---------- this is found to be of type `Option<u16>`
|
||||
LL | | 3 => break 'out Some(3u16),
|
||||
... |
|
||||
LL | | _ => {}
|
||||
| | ^^ expected `Option<u16>`, found `()`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_________- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected enum `Option<u16>`
|
||||
found unit type `()`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -3,11 +3,14 @@ error[E0308]: `match` arms have incompatible types
|
||||
|
|
||||
LL | / match E::F {
|
||||
LL | | E::A => 1,
|
||||
| | - this is found to be of type `{integer}`
|
||||
LL | | E::B => 2,
|
||||
| | - this is found to be of type `{integer}`
|
||||
LL | | E::C => 3,
|
||||
| | - this is found to be of type `{integer}`
|
||||
LL | | E::D => 4,
|
||||
| | - this is found to be of type `{integer}`
|
||||
LL | | E::E => unimplemented!(""),
|
||||
| | ------------------ this and all prior arms are found to be of type `{integer}`
|
||||
LL | | E::F => "",
|
||||
| | ^^ expected integer, found `&str`
|
||||
LL | | };
|
||||
|
@ -4,22 +4,15 @@ error[E0308]: `match` arms have incompatible types
|
||||
LL | / match num {
|
||||
LL | | 1 => {
|
||||
LL | | cx.answer_str("hi");
|
||||
| | -------------------- this is found to be of type `()`
|
||||
| | --------------------
|
||||
| | | |
|
||||
| | | help: consider removing this semicolon
|
||||
| | this is found to be of type `()`
|
||||
LL | | }
|
||||
LL | | _ => cx.answer_str("hi"),
|
||||
| | ^^^^^^^^^^^^^^^^^^^ expected `()`, found future
|
||||
LL | | }
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
help: consider removing this semicolon
|
||||
|
|
||||
LL - cx.answer_str("hi");
|
||||
LL + cx.answer_str("hi")
|
||||
|
|
||||
help: consider using a semicolon here, but this will discard any values in the match arms
|
||||
|
|
||||
LL | };
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -11,10 +11,6 @@ LL | | }
|
||||
|
|
||||
= note: expected reference `&S`
|
||||
found reference `&R`
|
||||
help: consider using a semicolon here, but this will discard any values in the match arms
|
||||
|
|
||||
LL | };
|
||||
| +
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-unsafe-trait-obj-match.rs:26:21
|
||||
|
Loading…
Reference in New Issue
Block a user