Auto merge of #103083 - Dylan-DPC:rollup-97cvwdv, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #102773 (Use semaphores for thread parking on Apple platforms) - #102884 (resolve: Some cleanup, asserts and tests for lifetime ribs) - #102954 (Add missing checks for `doc(cfg_hide(...))`) - #102998 (Drop temporaries created in a condition, even if it's a let chain) - #103003 (Fix `suggest_floating_point_literal` ICE) - #103041 (Update cargo) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c93ef33700
18 changed files with 610 additions and 104 deletions
|
@ -387,32 +387,58 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
then: &Block,
|
||||
else_opt: Option<&Expr>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let lowered_cond = self.lower_expr(cond);
|
||||
let new_cond = self.manage_let_cond(lowered_cond);
|
||||
let lowered_cond = self.lower_cond(cond);
|
||||
let then_expr = self.lower_block_expr(then);
|
||||
if let Some(rslt) = else_opt {
|
||||
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
|
||||
hir::ExprKind::If(
|
||||
lowered_cond,
|
||||
self.arena.alloc(then_expr),
|
||||
Some(self.lower_expr(rslt)),
|
||||
)
|
||||
} else {
|
||||
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
|
||||
hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
|
||||
}
|
||||
}
|
||||
|
||||
// If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
|
||||
// in a temporary block.
|
||||
fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
|
||||
fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
|
||||
match expr.kind {
|
||||
hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
||||
hir::ExprKind::Let(..) => true,
|
||||
// Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
|
||||
// so that temporaries created in the condition don't live beyond it.
|
||||
fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
|
||||
fn has_let_expr(expr: &Expr) -> bool {
|
||||
match &expr.kind {
|
||||
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
||||
ExprKind::Let(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
if has_let_expr(cond) {
|
||||
cond
|
||||
} else {
|
||||
let reason = DesugaringKind::CondTemporary;
|
||||
let span_block = self.mark_span_with_reason(reason, cond.span, None);
|
||||
self.expr_drop_temps(span_block, cond, AttrVec::new())
|
||||
|
||||
// We have to take special care for `let` exprs in the condition, e.g. in
|
||||
// `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
|
||||
// condition in this case.
|
||||
//
|
||||
// In order to mantain the drop behavior for the non `let` parts of the condition,
|
||||
// we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
|
||||
// gets transformed into `if { let _t = foo; _t } && let pat = val`
|
||||
match &cond.kind {
|
||||
ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
|
||||
if has_let_expr(cond) =>
|
||||
{
|
||||
let op = self.lower_binop(*op);
|
||||
let lhs = self.lower_cond(lhs);
|
||||
let rhs = self.lower_cond(rhs);
|
||||
|
||||
self.arena.alloc(self.expr(
|
||||
cond.span,
|
||||
hir::ExprKind::Binary(op, lhs, rhs),
|
||||
AttrVec::new(),
|
||||
))
|
||||
}
|
||||
ExprKind::Let(..) => self.lower_expr(cond),
|
||||
_ => {
|
||||
let cond = self.lower_expr(cond);
|
||||
let reason = DesugaringKind::CondTemporary;
|
||||
let span_block = self.mark_span_with_reason(reason, cond.span, None);
|
||||
self.expr_drop_temps(span_block, cond, AttrVec::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
body: &Block,
|
||||
opt_label: Option<Label>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
|
||||
let new_cond = self.manage_let_cond(lowered_cond);
|
||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
|
||||
let then = self.lower_block_expr(body);
|
||||
let expr_break = self.expr_break(span, AttrVec::new());
|
||||
let stmt_break = self.stmt_expr(span, expr_break);
|
||||
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
|
||||
let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
|
||||
let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
|
||||
let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
|
||||
let if_expr = self.expr(span, if_kind, AttrVec::new());
|
||||
let block = self.block_expr(self.arena.alloc(if_expr));
|
||||
let span = self.lower_span(span.with_hi(cond.span.hi()));
|
||||
|
|
|
@ -145,6 +145,9 @@ passes_doc_test_takes_list =
|
|||
passes_doc_primitive =
|
||||
`doc(primitive)` should never have been stable
|
||||
|
||||
passes_doc_cfg_hide_takes_list =
|
||||
`#[doc(cfg_hide(...)]` takes a list of attributes
|
||||
|
||||
passes_doc_test_unknown_any =
|
||||
unknown `doc` attribute `{$path}`
|
||||
|
||||
|
|
|
@ -934,6 +934,22 @@ impl CheckAttrVisitor<'_> {
|
|||
is_valid
|
||||
}
|
||||
|
||||
/// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
|
||||
/// Returns `true` if valid.
|
||||
fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
|
||||
if meta.meta_item_list().is_some() {
|
||||
true
|
||||
} else {
|
||||
self.tcx.emit_spanned_lint(
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
hir_id,
|
||||
meta.span(),
|
||||
errors::DocCfgHideTakesList,
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
|
||||
///
|
||||
/// `specified_inline` should be initialized to `None` and kept for the scope
|
||||
|
@ -987,6 +1003,13 @@ impl CheckAttrVisitor<'_> {
|
|||
is_valid = false;
|
||||
}
|
||||
|
||||
sym::cfg_hide
|
||||
if !self.check_attr_crate_level(attr, meta, hir_id)
|
||||
|| !self.check_doc_cfg_hide(meta, hir_id) =>
|
||||
{
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
sym::inline | sym::no_inline
|
||||
if !self.check_doc_inline(
|
||||
attr,
|
||||
|
|
|
@ -271,6 +271,10 @@ pub struct DocTestUnknown {
|
|||
#[diag(passes::doc_test_takes_list)]
|
||||
pub struct DocTestTakesList;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes::doc_cfg_hide_takes_list)]
|
||||
pub struct DocCfgHideTakesList;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes::doc_primitive)]
|
||||
pub struct DocPrimitive;
|
||||
|
|
|
@ -224,22 +224,14 @@ enum LifetimeUseSet {
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum LifetimeRibKind {
|
||||
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
|
||||
Item,
|
||||
|
||||
// -- Ribs introducing named lifetimes
|
||||
//
|
||||
/// This rib declares generic parameters.
|
||||
/// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
|
||||
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
|
||||
|
||||
/// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
|
||||
/// generics. We are disallowing this until we can decide on how we want to handle non-'static
|
||||
/// lifetimes in const generics. See issue #74052 for discussion.
|
||||
ConstGeneric,
|
||||
|
||||
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
|
||||
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
|
||||
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
|
||||
AnonConst,
|
||||
|
||||
// -- Ribs introducing unnamed lifetimes
|
||||
//
|
||||
/// Create a new anonymous lifetime parameter and reference it.
|
||||
///
|
||||
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
|
||||
|
@ -256,16 +248,31 @@ enum LifetimeRibKind {
|
|||
/// ```
|
||||
AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
|
||||
|
||||
/// Replace all anonymous lifetimes by provided lifetime.
|
||||
Elided(LifetimeRes),
|
||||
|
||||
// -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
|
||||
//
|
||||
/// Give a hard error when either `&` or `'_` is written. Used to
|
||||
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
||||
/// error on default object bounds (e.g., `Box<dyn Foo>`).
|
||||
AnonymousReportError,
|
||||
|
||||
/// Replace all anonymous lifetimes by provided lifetime.
|
||||
Elided(LifetimeRes),
|
||||
|
||||
/// Signal we cannot find which should be the anonymous lifetime.
|
||||
ElisionFailure,
|
||||
|
||||
/// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
|
||||
/// generics. We are disallowing this until we can decide on how we want to handle non-'static
|
||||
/// lifetimes in const generics. See issue #74052 for discussion.
|
||||
ConstGeneric,
|
||||
|
||||
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
|
||||
/// This function will emit an error if `generic_const_exprs` is not enabled, the body
|
||||
/// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
|
||||
AnonConst,
|
||||
|
||||
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
|
||||
Item,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -748,35 +755,31 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
|
||||
match foreign_item.kind {
|
||||
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
||||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|this| visit::walk_foreign_item(this, foreign_item),
|
||||
)
|
||||
});
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|this| visit::walk_foreign_item(this, foreign_item),
|
||||
);
|
||||
}
|
||||
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
|
||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
||||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
span: generics.span,
|
||||
},
|
||||
|this| visit::walk_foreign_item(this, foreign_item),
|
||||
)
|
||||
});
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
span: generics.span,
|
||||
},
|
||||
|this| visit::walk_foreign_item(this, foreign_item),
|
||||
);
|
||||
}
|
||||
ForeignItemKind::Static(..) => {
|
||||
self.with_item_rib(|this| {
|
||||
self.with_static_rib(|this| {
|
||||
visit::walk_foreign_item(this, foreign_item);
|
||||
});
|
||||
}
|
||||
|
@ -1391,9 +1394,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
return self.resolve_anonymous_lifetime(lifetime, false);
|
||||
}
|
||||
|
||||
let mut indices = (0..self.lifetime_ribs.len()).rev();
|
||||
for i in &mut indices {
|
||||
let rib = &self.lifetime_ribs[i];
|
||||
let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
|
||||
while let Some(rib) = lifetime_rib_iter.next() {
|
||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
|
||||
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
|
||||
|
@ -1423,9 +1425,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
} else {
|
||||
LifetimeUseSet::Many
|
||||
}),
|
||||
LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ConstGeneric
|
||||
| LifetimeRibKind::AnonConst => None,
|
||||
LifetimeRibKind::Generics { .. } => None,
|
||||
LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
|
||||
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
})
|
||||
.unwrap_or(LifetimeUseSet::Many);
|
||||
debug!(?use_ctxt, ?use_set);
|
||||
|
@ -1460,13 +1463,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||
| LifetimeRibKind::Elided(_)
|
||||
| LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::AnonymousReportError => {}
|
||||
}
|
||||
}
|
||||
|
||||
let mut outer_res = None;
|
||||
for i in indices {
|
||||
let rib = &self.lifetime_ribs[i];
|
||||
for rib in lifetime_rib_iter {
|
||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
|
||||
outer_res = Some(outer);
|
||||
|
@ -1493,8 +1499,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
count: 1,
|
||||
};
|
||||
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
||||
for i in (0..self.lifetime_ribs.len()).rev() {
|
||||
let rib = &mut self.lifetime_ribs[i];
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
debug!(?rib.kind);
|
||||
match rib.kind {
|
||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
||||
|
@ -1534,9 +1539,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
return;
|
||||
}
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ConstGeneric
|
||||
| LifetimeRibKind::AnonConst => {}
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||
LifetimeRibKind::AnonConst => {
|
||||
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
|
||||
span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
|
||||
|
@ -1751,9 +1758,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
|
||||
break;
|
||||
}
|
||||
LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ConstGeneric
|
||||
| LifetimeRibKind::AnonConst => {}
|
||||
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||
LifetimeRibKind::AnonConst => {
|
||||
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
|
||||
span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2204,7 +2213,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
}
|
||||
|
||||
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
|
||||
self.with_item_rib(|this| {
|
||||
self.with_static_rib(|this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||
this.visit_ty(ty);
|
||||
});
|
||||
|
@ -2399,11 +2408,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
self.label_ribs.pop();
|
||||
}
|
||||
|
||||
fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
let kind = ItemRibKind(HasGenericParams::No);
|
||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
||||
this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||
})
|
||||
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||
}
|
||||
|
||||
// HACK(min_const_generics,const_evaluatable_unchecked): We
|
||||
|
@ -3938,7 +3945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
fn_id: NodeId,
|
||||
async_node_id: Option<(NodeId, Span)>,
|
||||
) {
|
||||
if let Some((async_node_id, _)) = async_node_id {
|
||||
if let Some((async_node_id, span)) = async_node_id {
|
||||
let mut extra_lifetime_params =
|
||||
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
|
@ -3952,7 +3959,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
extra_lifetime_params.extend(earlier_fresh);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
LifetimeRibKind::Generics { .. } => {}
|
||||
_ => {
|
||||
// We are in a function definition. We should only find `Generics`
|
||||
// and `AnonymousCreateParameter` inside the innermost `Item`.
|
||||
span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
|
||||
|
|
|
@ -2937,19 +2937,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span,
|
||||
_ => return,
|
||||
};
|
||||
match (
|
||||
trait_ref.skip_binder().self_ty().kind(),
|
||||
trait_ref.skip_binder().substs.type_at(1).kind(),
|
||||
) {
|
||||
(ty::Float(_), ty::Infer(InferTy::IntVar(_))) => {
|
||||
err.span_suggestion_verbose(
|
||||
rhs_span.shrink_to_hi(),
|
||||
"consider using a floating-point literal by writing it with `.0`",
|
||||
".0",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
|
||||
&& let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
rhs_span.shrink_to_hi(),
|
||||
"consider using a floating-point literal by writing it with `.0`",
|
||||
".0",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue