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
|
@ -297,7 +297,7 @@ dependencies = [
|
||||||
"cargo-test-macro",
|
"cargo-test-macro",
|
||||||
"cargo-test-support",
|
"cargo-test-support",
|
||||||
"cargo-util",
|
"cargo-util",
|
||||||
"clap 4.0.9",
|
"clap 4.0.15",
|
||||||
"crates-io",
|
"crates-io",
|
||||||
"curl",
|
"curl",
|
||||||
"curl-sys",
|
"curl-sys",
|
||||||
|
@ -439,7 +439,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo-util"
|
name = "cargo-util"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
|
@ -602,9 +602,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.0.9"
|
version = "4.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30607dd93c420c6f1f80b544be522a0238a7db35e6a12968d28910983fee0df0"
|
checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|
|
@ -387,32 +387,58 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
then: &Block,
|
then: &Block,
|
||||||
else_opt: Option<&Expr>,
|
else_opt: Option<&Expr>,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let lowered_cond = self.lower_expr(cond);
|
let lowered_cond = self.lower_cond(cond);
|
||||||
let new_cond = self.manage_let_cond(lowered_cond);
|
|
||||||
let then_expr = self.lower_block_expr(then);
|
let then_expr = self.lower_block_expr(then);
|
||||||
if let Some(rslt) = else_opt {
|
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 {
|
} 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`
|
// Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
|
||||||
// in a temporary block.
|
// so that temporaries created in the condition don't live beyond it.
|
||||||
fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
|
fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
|
||||||
fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
|
fn has_let_expr(expr: &Expr) -> bool {
|
||||||
match expr.kind {
|
match &expr.kind {
|
||||||
hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
||||||
hir::ExprKind::Let(..) => true,
|
ExprKind::Let(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if has_let_expr(cond) {
|
|
||||||
cond
|
// We have to take special care for `let` exprs in the condition, e.g. in
|
||||||
} else {
|
// `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
|
||||||
let reason = DesugaringKind::CondTemporary;
|
// condition in this case.
|
||||||
let span_block = self.mark_span_with_reason(reason, cond.span, None);
|
//
|
||||||
self.expr_drop_temps(span_block, cond, AttrVec::new())
|
// 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,
|
body: &Block,
|
||||||
opt_label: Option<Label>,
|
opt_label: Option<Label>,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
|
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
|
||||||
let new_cond = self.manage_let_cond(lowered_cond);
|
|
||||||
let then = self.lower_block_expr(body);
|
let then = self.lower_block_expr(body);
|
||||||
let expr_break = self.expr_break(span, AttrVec::new());
|
let expr_break = self.expr_break(span, AttrVec::new());
|
||||||
let stmt_break = self.stmt_expr(span, expr_break);
|
let stmt_break = self.stmt_expr(span, expr_break);
|
||||||
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
|
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 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 if_expr = self.expr(span, if_kind, AttrVec::new());
|
||||||
let block = self.block_expr(self.arena.alloc(if_expr));
|
let block = self.block_expr(self.arena.alloc(if_expr));
|
||||||
let span = self.lower_span(span.with_hi(cond.span.hi()));
|
let span = self.lower_span(span.with_hi(cond.span.hi()));
|
||||||
|
|
|
@ -145,6 +145,9 @@ passes_doc_test_takes_list =
|
||||||
passes_doc_primitive =
|
passes_doc_primitive =
|
||||||
`doc(primitive)` should never have been stable
|
`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 =
|
passes_doc_test_unknown_any =
|
||||||
unknown `doc` attribute `{$path}`
|
unknown `doc` attribute `{$path}`
|
||||||
|
|
||||||
|
|
|
@ -934,6 +934,22 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid
|
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.
|
/// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
|
||||||
///
|
///
|
||||||
/// `specified_inline` should be initialized to `None` and kept for the scope
|
/// `specified_inline` should be initialized to `None` and kept for the scope
|
||||||
|
@ -987,6 +1003,13 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid = false;
|
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
|
sym::inline | sym::no_inline
|
||||||
if !self.check_doc_inline(
|
if !self.check_doc_inline(
|
||||||
attr,
|
attr,
|
||||||
|
|
|
@ -271,6 +271,10 @@ pub struct DocTestUnknown {
|
||||||
#[diag(passes::doc_test_takes_list)]
|
#[diag(passes::doc_test_takes_list)]
|
||||||
pub struct DocTestTakesList;
|
pub struct DocTestTakesList;
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(passes::doc_cfg_hide_takes_list)]
|
||||||
|
pub struct DocCfgHideTakesList;
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(passes::doc_primitive)]
|
#[diag(passes::doc_primitive)]
|
||||||
pub struct DocPrimitive;
|
pub struct DocPrimitive;
|
||||||
|
|
|
@ -224,22 +224,14 @@ enum LifetimeUseSet {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
enum LifetimeRibKind {
|
enum LifetimeRibKind {
|
||||||
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
|
// -- Ribs introducing named lifetimes
|
||||||
Item,
|
//
|
||||||
|
|
||||||
/// This rib declares generic parameters.
|
/// This rib declares generic parameters.
|
||||||
|
/// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
|
||||||
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
|
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
|
||||||
|
|
||||||
/// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
|
// -- Ribs introducing unnamed lifetimes
|
||||||
/// 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,
|
|
||||||
|
|
||||||
/// Create a new anonymous lifetime parameter and reference it.
|
/// Create a new anonymous lifetime parameter and reference it.
|
||||||
///
|
///
|
||||||
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
|
/// 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 },
|
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
|
/// Give a hard error when either `&` or `'_` is written. Used to
|
||||||
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
||||||
/// error on default object bounds (e.g., `Box<dyn Foo>`).
|
/// error on default object bounds (e.g., `Box<dyn Foo>`).
|
||||||
AnonymousReportError,
|
AnonymousReportError,
|
||||||
|
|
||||||
/// Replace all anonymous lifetimes by provided lifetime.
|
|
||||||
Elided(LifetimeRes),
|
|
||||||
|
|
||||||
/// Signal we cannot find which should be the anonymous lifetime.
|
/// Signal we cannot find which should be the anonymous lifetime.
|
||||||
ElisionFailure,
|
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)]
|
#[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) {
|
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
|
||||||
match foreign_item.kind {
|
match foreign_item.kind {
|
||||||
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
self.with_generic_param_rib(
|
||||||
this.with_generic_param_rib(
|
&generics.params,
|
||||||
&generics.params,
|
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
LifetimeRibKind::Generics {
|
||||||
LifetimeRibKind::Generics {
|
binder: foreign_item.id,
|
||||||
binder: foreign_item.id,
|
kind: LifetimeBinderKind::Item,
|
||||||
kind: LifetimeBinderKind::Item,
|
span: generics.span,
|
||||||
span: generics.span,
|
},
|
||||||
},
|
|this| visit::walk_foreign_item(this, foreign_item),
|
||||||
|this| visit::walk_foreign_item(this, foreign_item),
|
);
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
|
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
self.with_generic_param_rib(
|
||||||
this.with_generic_param_rib(
|
&generics.params,
|
||||||
&generics.params,
|
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
||||||
ItemRibKind(HasGenericParams::Yes(generics.span)),
|
LifetimeRibKind::Generics {
|
||||||
LifetimeRibKind::Generics {
|
binder: foreign_item.id,
|
||||||
binder: foreign_item.id,
|
kind: LifetimeBinderKind::Function,
|
||||||
kind: LifetimeBinderKind::Function,
|
span: generics.span,
|
||||||
span: generics.span,
|
},
|
||||||
},
|
|this| visit::walk_foreign_item(this, foreign_item),
|
||||||
|this| visit::walk_foreign_item(this, foreign_item),
|
);
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(..) => {
|
ForeignItemKind::Static(..) => {
|
||||||
self.with_item_rib(|this| {
|
self.with_static_rib(|this| {
|
||||||
visit::walk_foreign_item(this, foreign_item);
|
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);
|
return self.resolve_anonymous_lifetime(lifetime, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut indices = (0..self.lifetime_ribs.len()).rev();
|
let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
|
||||||
for i in &mut indices {
|
while let Some(rib) = lifetime_rib_iter.next() {
|
||||||
let rib = &self.lifetime_ribs[i];
|
|
||||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||||
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
|
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
|
||||||
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
|
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
|
||||||
|
@ -1423,9 +1425,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
} else {
|
} else {
|
||||||
LifetimeUseSet::Many
|
LifetimeUseSet::Many
|
||||||
}),
|
}),
|
||||||
LifetimeRibKind::Generics { .. }
|
LifetimeRibKind::Generics { .. } => None,
|
||||||
| LifetimeRibKind::ConstGeneric
|
LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
|
||||||
| LifetimeRibKind::AnonConst => None,
|
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(LifetimeUseSet::Many);
|
.unwrap_or(LifetimeUseSet::Many);
|
||||||
debug!(?use_ctxt, ?use_set);
|
debug!(?use_ctxt, ?use_set);
|
||||||
|
@ -1460,13 +1463,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||||
|
| LifetimeRibKind::Elided(_)
|
||||||
|
| LifetimeRibKind::Generics { .. }
|
||||||
|
| LifetimeRibKind::ElisionFailure
|
||||||
|
| LifetimeRibKind::AnonymousReportError => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut outer_res = None;
|
let mut outer_res = None;
|
||||||
for i in indices {
|
for rib in lifetime_rib_iter {
|
||||||
let rib = &self.lifetime_ribs[i];
|
|
||||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||||
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
|
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
|
||||||
outer_res = Some(outer);
|
outer_res = Some(outer);
|
||||||
|
@ -1493,8 +1499,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
count: 1,
|
count: 1,
|
||||||
};
|
};
|
||||||
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
||||||
for i in (0..self.lifetime_ribs.len()).rev() {
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
let rib = &mut self.lifetime_ribs[i];
|
|
||||||
debug!(?rib.kind);
|
debug!(?rib.kind);
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
||||||
|
@ -1534,9 +1539,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LifetimeRibKind::Item => break,
|
LifetimeRibKind::Item => break,
|
||||||
LifetimeRibKind::Generics { .. }
|
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||||
| LifetimeRibKind::ConstGeneric
|
LifetimeRibKind::AnonConst => {
|
||||||
| 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);
|
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);
|
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LifetimeRibKind::Generics { .. }
|
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
|
||||||
| LifetimeRibKind::ConstGeneric
|
LifetimeRibKind::AnonConst => {
|
||||||
| 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) => {
|
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.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
});
|
});
|
||||||
|
@ -2399,11 +2408,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
self.label_ribs.pop();
|
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);
|
let kind = ItemRibKind(HasGenericParams::No);
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
|
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||||
this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(min_const_generics,const_evaluatable_unchecked): We
|
// HACK(min_const_generics,const_evaluatable_unchecked): We
|
||||||
|
@ -3938,7 +3945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
fn_id: NodeId,
|
fn_id: NodeId,
|
||||||
async_node_id: Option<(NodeId, Span)>,
|
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 =
|
let mut extra_lifetime_params =
|
||||||
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
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);
|
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);
|
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,
|
ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
match (
|
if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
|
||||||
trait_ref.skip_binder().self_ty().kind(),
|
&& let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
|
||||||
trait_ref.skip_binder().substs.type_at(1).kind(),
|
{
|
||||||
) {
|
err.span_suggestion_verbose(
|
||||||
(ty::Float(_), ty::Infer(InferTy::IntVar(_))) => {
|
rhs_span.shrink_to_hi(),
|
||||||
err.span_suggestion_verbose(
|
"consider using a floating-point literal by writing it with `.0`",
|
||||||
rhs_span.shrink_to_hi(),
|
".0",
|
||||||
"consider using a floating-point literal by writing it with `.0`",
|
Applicability::MaybeIncorrect,
|
||||||
".0",
|
);
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
131
library/std/src/sys/unix/thread_parker/darwin.rs
Normal file
131
library/std/src/sys/unix/thread_parker/darwin.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
//! Thread parking for Darwin-based systems.
|
||||||
|
//!
|
||||||
|
//! Darwin actually has futex syscalls (`__ulock_wait`/`__ulock_wake`), but they
|
||||||
|
//! cannot be used in `std` because they are non-public (their use will lead to
|
||||||
|
//! rejection from the App Store) and because they are only available starting
|
||||||
|
//! with macOS version 10.12, even though the minimum target version is 10.7.
|
||||||
|
//!
|
||||||
|
//! Therefore, we need to look for other synchronization primitives. Luckily, Darwin
|
||||||
|
//! supports semaphores, which allow us to implement the behaviour we need with
|
||||||
|
//! only one primitive (as opposed to a mutex-condvar pair). We use the semaphore
|
||||||
|
//! provided by libdispatch, as the underlying Mach semaphore is only dubiously
|
||||||
|
//! public.
|
||||||
|
|
||||||
|
use crate::pin::Pin;
|
||||||
|
use crate::sync::atomic::{
|
||||||
|
AtomicI8,
|
||||||
|
Ordering::{Acquire, Release},
|
||||||
|
};
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
type dispatch_semaphore_t = *mut crate::ffi::c_void;
|
||||||
|
type dispatch_time_t = u64;
|
||||||
|
|
||||||
|
const DISPATCH_TIME_NOW: dispatch_time_t = 0;
|
||||||
|
const DISPATCH_TIME_FOREVER: dispatch_time_t = !0;
|
||||||
|
|
||||||
|
// Contained in libSystem.dylib, which is linked by default.
|
||||||
|
extern "C" {
|
||||||
|
fn dispatch_time(when: dispatch_time_t, delta: i64) -> dispatch_time_t;
|
||||||
|
fn dispatch_semaphore_create(val: isize) -> dispatch_semaphore_t;
|
||||||
|
fn dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t) -> isize;
|
||||||
|
fn dispatch_semaphore_signal(dsema: dispatch_semaphore_t) -> isize;
|
||||||
|
fn dispatch_release(object: *mut crate::ffi::c_void);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY: i8 = 0;
|
||||||
|
const NOTIFIED: i8 = 1;
|
||||||
|
const PARKED: i8 = -1;
|
||||||
|
|
||||||
|
pub struct Parker {
|
||||||
|
semaphore: dispatch_semaphore_t,
|
||||||
|
state: AtomicI8,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for Parker {}
|
||||||
|
unsafe impl Send for Parker {}
|
||||||
|
|
||||||
|
impl Parker {
|
||||||
|
pub unsafe fn new(parker: *mut Parker) {
|
||||||
|
let semaphore = dispatch_semaphore_create(0);
|
||||||
|
assert!(
|
||||||
|
!semaphore.is_null(),
|
||||||
|
"failed to create dispatch semaphore for thread synchronization"
|
||||||
|
);
|
||||||
|
parker.write(Parker { semaphore, state: AtomicI8::new(EMPTY) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not need `Pin`, but other implementation do.
|
||||||
|
pub unsafe fn park(self: Pin<&Self>) {
|
||||||
|
// The semaphore counter must be zero at this point, because unparking
|
||||||
|
// threads will not actually increase it until we signalled that we
|
||||||
|
// are waiting.
|
||||||
|
|
||||||
|
// Change NOTIFIED to EMPTY and EMPTY to PARKED.
|
||||||
|
if self.state.fetch_sub(1, Acquire) == NOTIFIED {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Another thread may increase the semaphore counter from this point on.
|
||||||
|
// If it is faster than us, we will decrement it again immediately below.
|
||||||
|
// If we are faster, we wait.
|
||||||
|
|
||||||
|
// Ensure that the semaphore counter has actually been decremented, even
|
||||||
|
// if the call timed out for some reason.
|
||||||
|
while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
|
||||||
|
|
||||||
|
// At this point, the semaphore counter is zero again.
|
||||||
|
|
||||||
|
// We were definitely woken up, so we don't need to check the state.
|
||||||
|
// Still, we need to reset the state using a swap to observe the state
|
||||||
|
// change with acquire ordering.
|
||||||
|
self.state.swap(EMPTY, Acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not need `Pin`, but other implementation do.
|
||||||
|
pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
|
||||||
|
if self.state.fetch_sub(1, Acquire) == NOTIFIED {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nanos = dur.as_nanos().try_into().unwrap_or(i64::MAX);
|
||||||
|
let timeout = dispatch_time(DISPATCH_TIME_NOW, nanos);
|
||||||
|
|
||||||
|
let timeout = dispatch_semaphore_wait(self.semaphore, timeout) != 0;
|
||||||
|
|
||||||
|
let state = self.state.swap(EMPTY, Acquire);
|
||||||
|
if state == NOTIFIED && timeout {
|
||||||
|
// If the state was NOTIFIED but semaphore_wait returned without
|
||||||
|
// decrementing the count because of a timeout, it means another
|
||||||
|
// thread is about to call semaphore_signal. We must wait for that
|
||||||
|
// to happen to ensure the semaphore count is reset.
|
||||||
|
while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
|
||||||
|
} else {
|
||||||
|
// Either a timeout occurred and we reset the state before any thread
|
||||||
|
// tried to wake us up, or we were woken up and reset the state,
|
||||||
|
// making sure to observe the state change with acquire ordering.
|
||||||
|
// Either way, the semaphore counter is now zero again.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not need `Pin`, but other implementation do.
|
||||||
|
pub fn unpark(self: Pin<&Self>) {
|
||||||
|
let state = self.state.swap(NOTIFIED, Release);
|
||||||
|
if state == PARKED {
|
||||||
|
unsafe {
|
||||||
|
dispatch_semaphore_signal(self.semaphore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Parker {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// SAFETY:
|
||||||
|
// We always ensure that the semaphore count is reset, so this will
|
||||||
|
// never cause an exception.
|
||||||
|
unsafe {
|
||||||
|
dispatch_release(self.semaphore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,18 @@
|
||||||
)))]
|
)))]
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_os = "netbsd")] {
|
if #[cfg(all(
|
||||||
|
any(
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "watchos",
|
||||||
|
target_os = "tvos",
|
||||||
|
),
|
||||||
|
not(miri),
|
||||||
|
))] {
|
||||||
|
mod darwin;
|
||||||
|
pub use darwin::Parker;
|
||||||
|
} else if #[cfg(target_os = "netbsd")] {
|
||||||
mod netbsd;
|
mod netbsd;
|
||||||
pub use netbsd::Parker;
|
pub use netbsd::Parker;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -244,6 +244,28 @@ fn test_try_panic_any_message_unit_struct() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_park_unpark_before() {
|
||||||
|
for _ in 0..10 {
|
||||||
|
thread::current().unpark();
|
||||||
|
thread::park();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_park_unpark_called_other_thread() {
|
||||||
|
for _ in 0..10 {
|
||||||
|
let th = thread::current();
|
||||||
|
|
||||||
|
let _guard = thread::spawn(move || {
|
||||||
|
super::sleep(Duration::from_millis(50));
|
||||||
|
th.unpark();
|
||||||
|
});
|
||||||
|
|
||||||
|
thread::park();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_park_timeout_unpark_before() {
|
fn test_park_timeout_unpark_before() {
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
|
|
11
src/test/rustdoc-ui/doc_cfg_hide.rs
Normal file
11
src/test/rustdoc-ui/doc_cfg_hide.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#![feature(doc_cfg_hide)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
|
#![doc(cfg_hide = "test")] //~ ERROR
|
||||||
|
//~^ WARN
|
||||||
|
#![doc(cfg_hide)] //~ ERROR
|
||||||
|
//~^ WARN
|
||||||
|
|
||||||
|
#[doc(cfg_hide(doc))] //~ ERROR
|
||||||
|
//~^ WARN
|
||||||
|
pub fn foo() {}
|
40
src/test/rustdoc-ui/doc_cfg_hide.stderr
Normal file
40
src/test/rustdoc-ui/doc_cfg_hide.stderr
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
error: this attribute can only be applied at the crate level
|
||||||
|
--> $DIR/doc_cfg_hide.rs:9:7
|
||||||
|
|
|
||||||
|
LL | #[doc(cfg_hide(doc))]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/doc_cfg_hide.rs:2:9
|
||||||
|
|
|
||||||
|
LL | #![deny(warnings)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
||||||
|
help: to apply to the crate, use an inner attribute
|
||||||
|
|
|
||||||
|
LL | #![doc(cfg_hide(doc))]
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: `#[doc(cfg_hide(...)]` takes a list of attributes
|
||||||
|
--> $DIR/doc_cfg_hide.rs:4:8
|
||||||
|
|
|
||||||
|
LL | #![doc(cfg_hide = "test")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
|
||||||
|
error: `#[doc(cfg_hide(...)]` takes a list of attributes
|
||||||
|
--> $DIR/doc_cfg_hide.rs:6:8
|
||||||
|
|
|
||||||
|
LL | #![doc(cfg_hide)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
// compile-flags: -Z validate-mir
|
||||||
|
#![feature(let_chains)]
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
@ -116,6 +118,58 @@ impl DropOrderCollector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn let_chain(&self) {
|
||||||
|
// take the "then" branch
|
||||||
|
if self.option_loud_drop(2).is_some() // 2
|
||||||
|
&& self.option_loud_drop(1).is_some() // 1
|
||||||
|
&& let Some(_d) = self.option_loud_drop(4) { // 4
|
||||||
|
self.print(3); // 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// take the "else" branch
|
||||||
|
if self.option_loud_drop(6).is_some() // 2
|
||||||
|
&& self.option_loud_drop(5).is_some() // 1
|
||||||
|
&& let None = self.option_loud_drop(7) { // 3
|
||||||
|
unreachable!();
|
||||||
|
} else {
|
||||||
|
self.print(8); // 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// let exprs interspersed
|
||||||
|
if self.option_loud_drop(9).is_some() // 1
|
||||||
|
&& let Some(_d) = self.option_loud_drop(13) // 5
|
||||||
|
&& self.option_loud_drop(10).is_some() // 2
|
||||||
|
&& let Some(_e) = self.option_loud_drop(12) { // 4
|
||||||
|
self.print(11); // 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// let exprs first
|
||||||
|
if let Some(_d) = self.option_loud_drop(18) // 5
|
||||||
|
&& let Some(_e) = self.option_loud_drop(17) // 4
|
||||||
|
&& self.option_loud_drop(14).is_some() // 1
|
||||||
|
&& self.option_loud_drop(15).is_some() { // 2
|
||||||
|
self.print(16); // 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// let exprs last
|
||||||
|
if self.option_loud_drop(20).is_some() // 2
|
||||||
|
&& self.option_loud_drop(19).is_some() // 1
|
||||||
|
&& let Some(_d) = self.option_loud_drop(23) // 5
|
||||||
|
&& let Some(_e) = self.option_loud_drop(22) { // 4
|
||||||
|
self.print(21); // 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn while_(&self) {
|
||||||
|
let mut v = self.option_loud_drop(4);
|
||||||
|
while let Some(_d) = v
|
||||||
|
&& self.option_loud_drop(1).is_some()
|
||||||
|
&& self.option_loud_drop(2).is_some() {
|
||||||
|
self.print(3);
|
||||||
|
v = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_sorted(self) {
|
fn assert_sorted(self) {
|
||||||
assert!(
|
assert!(
|
||||||
self.0
|
self.0
|
||||||
|
@ -142,4 +196,14 @@ fn main() {
|
||||||
let collector = DropOrderCollector::default();
|
let collector = DropOrderCollector::default();
|
||||||
collector.match_();
|
collector.match_();
|
||||||
collector.assert_sorted();
|
collector.assert_sorted();
|
||||||
|
|
||||||
|
println!("-- let chain --");
|
||||||
|
let collector = DropOrderCollector::default();
|
||||||
|
collector.let_chain();
|
||||||
|
collector.assert_sorted();
|
||||||
|
|
||||||
|
println!("-- while --");
|
||||||
|
let collector = DropOrderCollector::default();
|
||||||
|
collector.while_();
|
||||||
|
collector.assert_sorted();
|
||||||
}
|
}
|
||||||
|
|
28
src/test/ui/lifetimes/unusual-rib-combinations.rs
Normal file
28
src/test/ui/lifetimes/unusual-rib-combinations.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#![feature(inline_const)]
|
||||||
|
|
||||||
|
struct S<'a>(&'a u8);
|
||||||
|
fn foo() {}
|
||||||
|
|
||||||
|
// Paren generic args in AnonConst
|
||||||
|
fn a() -> [u8; foo::()] {
|
||||||
|
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paren generic args in ConstGeneric
|
||||||
|
fn b<const C: u8()>() {}
|
||||||
|
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
|
||||||
|
// Paren generic args in AnonymousReportError
|
||||||
|
fn c<T = u8()>() {}
|
||||||
|
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
//~| ERROR defaults for type parameters are only allowed in
|
||||||
|
//~| WARN this was previously accepted
|
||||||
|
|
||||||
|
// Elided lifetime in path in ConstGeneric
|
||||||
|
fn d<const C: S>() {}
|
||||||
|
//~^ ERROR missing lifetime specifier
|
||||||
|
//~| ERROR `S<'static>` is forbidden as the type of a const generic parameter
|
||||||
|
|
||||||
|
fn main() {}
|
61
src/test/ui/lifetimes/unusual-rib-combinations.stderr
Normal file
61
src/test/ui/lifetimes/unusual-rib-combinations.stderr
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:24:15
|
||||||
|
|
|
||||||
|
LL | fn d<const C: S>() {}
|
||||||
|
| ^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
||||||
|
LL | fn d<'a, const C: S<'a>>() {}
|
||||||
|
| +++ ++++
|
||||||
|
|
||||||
|
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:7:16
|
||||||
|
|
|
||||||
|
LL | fn a() -> [u8; foo::()] {
|
||||||
|
| ^^^^^^^ only `Fn` traits may use parentheses
|
||||||
|
|
||||||
|
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:14:15
|
||||||
|
|
|
||||||
|
LL | fn b<const C: u8()>() {}
|
||||||
|
| ^^^^ only `Fn` traits may use parentheses
|
||||||
|
|
||||||
|
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:18:10
|
||||||
|
|
|
||||||
|
LL | fn c<T = u8()>() {}
|
||||||
|
| ^^^^ only `Fn` traits may use parentheses
|
||||||
|
|
||||||
|
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:18:6
|
||||||
|
|
|
||||||
|
LL | fn c<T = u8()>() {}
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
|
||||||
|
= note: `#[deny(invalid_type_param_default)]` on by default
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:7:16
|
||||||
|
|
|
||||||
|
LL | fn a() -> [u8; foo::()] {
|
||||||
|
| ^^^^^^^ expected `usize`, found fn item
|
||||||
|
|
|
||||||
|
= note: expected type `usize`
|
||||||
|
found fn item `fn() {foo}`
|
||||||
|
|
||||||
|
error: `S<'static>` is forbidden as the type of a const generic parameter
|
||||||
|
--> $DIR/unusual-rib-combinations.rs:24:15
|
||||||
|
|
|
||||||
|
LL | fn d<const C: S>() {}
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: the only supported types are integers, `bool` and `char`
|
||||||
|
= help: more complex types are supported with `#![feature(adt_const_params)]`
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0106, E0214, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0106`.
|
16
src/test/ui/traits/issue-102989.rs
Normal file
16
src/test/ui/traits/issue-102989.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib"
|
||||||
|
|
||||||
|
#![feature(lang_items)]
|
||||||
|
#[lang="sized"]
|
||||||
|
trait Sized { } //~ ERROR found duplicate lang item `sized`
|
||||||
|
|
||||||
|
fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||||
|
//~^ ERROR `self` parameter is only allowed in associated functions
|
||||||
|
//~| ERROR cannot find type `Struct` in this scope
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
let x = x << 1;
|
||||||
|
//~^ ERROR the size for values of type `{integer}` cannot be known at compilation time
|
||||||
|
//~| ERROR cannot find value `x` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
59
src/test/ui/traits/issue-102989.stderr
Normal file
59
src/test/ui/traits/issue-102989.stderr
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
error: `self` parameter is only allowed in associated functions
|
||||||
|
--> $DIR/issue-102989.rs:7:15
|
||||||
|
|
|
||||||
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||||
|
| ^^^^ not semantically valid as function parameter
|
||||||
|
|
|
||||||
|
= note: associated functions are those in `impl` or `trait` definitions
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `Struct` in this scope
|
||||||
|
--> $DIR/issue-102989.rs:7:22
|
||||||
|
|
|
||||||
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||||
|
| ^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `x` in this scope
|
||||||
|
--> $DIR/issue-102989.rs:11:13
|
||||||
|
|
|
||||||
|
LL | let x = x << 1;
|
||||||
|
| ^ help: a local variable with a similar name exists: `f`
|
||||||
|
|
||||||
|
error[E0152]: found duplicate lang item `sized`
|
||||||
|
--> $DIR/issue-102989.rs:5:1
|
||||||
|
|
|
||||||
|
LL | trait Sized { }
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: the lang item is first defined in crate `core` (which `std` depends on)
|
||||||
|
= note: first definition in `core` loaded from SYSROOT/libcore-*.rlib
|
||||||
|
= note: second definition in the local crate (`issue_102989`)
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `{integer}` cannot be known at compilation time
|
||||||
|
--> $DIR/issue-102989.rs:11:15
|
||||||
|
|
|
||||||
|
LL | let x = x << 1;
|
||||||
|
| ^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `std::marker::Sized` is not implemented for `{integer}`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-102989.rs:7:42
|
||||||
|
|
|
||||||
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||||
|
| ---------- ^^^^ expected `&u32`, found `()`
|
||||||
|
| |
|
||||||
|
| implicitly returns `()` as its body has no tail or `return` expression
|
||||||
|
|
|
||||||
|
note: consider returning one of these bindings
|
||||||
|
--> $DIR/issue-102989.rs:7:30
|
||||||
|
|
|
||||||
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
|
||||||
|
| ^
|
||||||
|
...
|
||||||
|
LL | let x = x << 1;
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425.
|
||||||
|
For more information about an error, try `rustc --explain E0152`.
|
|
@ -1 +1 @@
|
||||||
Subproject commit b8f30cb23c4e5f20854a4f683325782b7cff9837
|
Subproject commit b332991a57c9d055f1864de1eed93e2178d49440
|
Loading…
Add table
Add a link
Reference in a new issue