Auto merge of #89414 - Manishearth:rollup-hs11bcq, r=Manishearth
Rollup of 8 pull requests Successful merges: - #88782 (Fix ICE when `start` lang item has wrong generics) - #89202 (Resolve infered types when complaining about unexpected call type ) - #89248 (Suggest similarly named associated items in trait impls) - #89303 (Add `#[must_not_suspend]` to some types in std) - #89306 (thread: implements available_concurrency on haiku) - #89314 (fix(lint): don't suggest refutable patterns to "fix" irrefutable bind) - #89370 (CTFE: tweak aggregate rvalue handling) - #89392 (bootstrap: Update comment in config.library.toml.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
598d89bf14
@ -197,12 +197,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
Aggregate(ref kind, ref operands) => {
|
||||
// active_field_index is for union initialization.
|
||||
let (dest, active_field_index) = match **kind {
|
||||
mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
|
||||
self.write_discriminant(variant_index, &dest)?;
|
||||
if adt_def.is_enum() {
|
||||
(self.place_downcast(&dest, variant_index)?, active_field_index)
|
||||
assert!(active_field_index.is_none());
|
||||
(self.place_downcast(&dest, variant_index)?, None)
|
||||
} else {
|
||||
if active_field_index.is_some() {
|
||||
assert_eq!(operands.len(), 1);
|
||||
}
|
||||
(dest, active_field_index)
|
||||
}
|
||||
}
|
||||
@ -211,12 +216,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
let op = self.eval_operand(operand, None)?;
|
||||
// Ignore zero-sized fields.
|
||||
if !op.layout.is_zst() {
|
||||
let field_index = active_field_index.unwrap_or(i);
|
||||
let field_dest = self.place_field(&dest, field_index)?;
|
||||
self.copy_op(&op, &field_dest)?;
|
||||
}
|
||||
let field_index = active_field_index.unwrap_or(i);
|
||||
let field_dest = self.place_field(&dest, field_index)?;
|
||||
self.copy_op(&op, &field_dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +255,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
Len(place) => {
|
||||
// FIXME(CTFE): don't allow computing the length of arrays in const eval
|
||||
let src = self.eval_place(place)?;
|
||||
let mplace = self.force_allocation(&src)?;
|
||||
let len = mplace.len(self)?;
|
||||
|
@ -300,7 +300,7 @@ language_item_table! {
|
||||
Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;
|
||||
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
|
||||
|
||||
Start, sym::start, start_fn, Target::Fn, GenericRequirement::None;
|
||||
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||
|
||||
EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
|
||||
EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
|
||||
|
@ -39,6 +39,13 @@ fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBu
|
||||
struct_span_err!(sess, sp, E0004, "{}", &error_message)
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum RefutableFlag {
|
||||
Irrefutable,
|
||||
Refutable,
|
||||
}
|
||||
use RefutableFlag::*;
|
||||
|
||||
struct MatchVisitor<'a, 'p, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||
@ -73,13 +80,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
|
||||
hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None),
|
||||
};
|
||||
self.check_irrefutable(&loc.pat, msg, sp);
|
||||
self.check_patterns(&loc.pat);
|
||||
self.check_patterns(&loc.pat, Irrefutable);
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||
intravisit::walk_param(self, param);
|
||||
self.check_irrefutable(¶m.pat, "function argument", None);
|
||||
self.check_patterns(¶m.pat);
|
||||
self.check_patterns(¶m.pat, Irrefutable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,9 +120,9 @@ impl PatCtxt<'_, '_> {
|
||||
}
|
||||
|
||||
impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
fn check_patterns(&self, pat: &Pat<'_>) {
|
||||
fn check_patterns(&self, pat: &Pat<'_>, rf: RefutableFlag) {
|
||||
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
||||
check_for_bindings_named_same_as_variants(self, pat);
|
||||
check_for_bindings_named_same_as_variants(self, pat, rf);
|
||||
}
|
||||
|
||||
fn lower_pattern(
|
||||
@ -145,7 +152,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
}
|
||||
|
||||
fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) {
|
||||
self.check_patterns(pat);
|
||||
self.check_patterns(pat, Refutable);
|
||||
let mut cx = self.new_cx(expr.hir_id);
|
||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
|
||||
check_let_reachability(&mut cx, pat.hir_id, tpat, span);
|
||||
@ -161,9 +168,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
|
||||
for arm in arms {
|
||||
// Check the arm for some things unrelated to exhaustiveness.
|
||||
self.check_patterns(&arm.pat);
|
||||
self.check_patterns(&arm.pat, Refutable);
|
||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||
self.check_patterns(pat);
|
||||
self.check_patterns(pat, Refutable);
|
||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
|
||||
check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span());
|
||||
}
|
||||
@ -297,7 +304,11 @@ fn const_not_var(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>) {
|
||||
fn check_for_bindings_named_same_as_variants(
|
||||
cx: &MatchVisitor<'_, '_, '_>,
|
||||
pat: &Pat<'_>,
|
||||
rf: RefutableFlag,
|
||||
) {
|
||||
pat.walk_always(|p| {
|
||||
if let hir::PatKind::Binding(_, _, ident, None) = p.kind {
|
||||
if let Some(ty::BindByValue(hir::Mutability::Not)) =
|
||||
@ -310,25 +321,31 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_, '_>, pat:
|
||||
variant.ident == ident && variant.ctor_kind == CtorKind::Const
|
||||
})
|
||||
{
|
||||
let variant_count = edef.variants.len();
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
BINDINGS_WITH_VARIANT_NAME,
|
||||
p.hir_id,
|
||||
p.span,
|
||||
|lint| {
|
||||
let ty_path = cx.tcx.def_path_str(edef.did);
|
||||
lint.build(&format!(
|
||||
let mut err = lint.build(&format!(
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
of the variants of the type `{}`",
|
||||
ident, ty_path
|
||||
))
|
||||
.code(error_code!(E0170))
|
||||
.span_suggestion(
|
||||
p.span,
|
||||
"to match on the variant, qualify the path",
|
||||
format!("{}::{}", ty_path, ident),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
));
|
||||
err.code(error_code!(E0170));
|
||||
// If this is an irrefutable pattern, and there's > 1 variant,
|
||||
// then we can't actually match on this. Applying the below
|
||||
// suggestion would produce code that breaks on `check_irrefutable`.
|
||||
if rf == Refutable || variant_count == 1 {
|
||||
err.span_suggestion(
|
||||
p.span,
|
||||
"to match on the variant, qualify the path",
|
||||
format!("{}::{}", ty_path, ident),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ impl<'a> Resolver<'a> {
|
||||
err.span_label(first_use_span, format!("first use of `{}`", name));
|
||||
err
|
||||
}
|
||||
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
||||
ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
@ -208,9 +208,17 @@ impl<'a> Resolver<'a> {
|
||||
trait_
|
||||
);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
if let Some(candidate) = candidate {
|
||||
err.span_suggestion(
|
||||
method.span,
|
||||
"there is an associated function with a similar name",
|
||||
candidate.to_ident_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
||||
ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
@ -220,9 +228,17 @@ impl<'a> Resolver<'a> {
|
||||
trait_
|
||||
);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
if let Some(candidate) = candidate {
|
||||
err.span_suggestion(
|
||||
type_.span,
|
||||
"there is an associated type with a similar name",
|
||||
candidate.to_ident_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
||||
ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
@ -232,6 +248,14 @@ impl<'a> Resolver<'a> {
|
||||
trait_
|
||||
);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
if let Some(candidate) = candidate {
|
||||
err.span_suggestion(
|
||||
const_.span,
|
||||
"there is an associated constant with a similar name",
|
||||
candidate.to_ident_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::VariableNotBoundInPattern(binding_error) => {
|
||||
|
@ -1309,14 +1309,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
use crate::ResolutionError::*;
|
||||
match &item.kind {
|
||||
AssocItemKind::Const(_default, _ty, _expr) => {
|
||||
debug!("resolve_implementation AssocItemKind::Const",);
|
||||
debug!("resolve_implementation AssocItemKind::Const");
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
this.check_trait_item(
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
|n, s| ConstNotMemberOfTrait(n, s),
|
||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
@ -1338,6 +1339,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
);
|
||||
}
|
||||
AssocItemKind::Fn(box FnKind(.., generics, _)) => {
|
||||
debug!("resolve_implementation AssocItemKind::Fn");
|
||||
// We also need a new scope for the impl item type parameters.
|
||||
this.with_generic_param_rib(
|
||||
generics,
|
||||
@ -1347,9 +1349,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
// exists in trait
|
||||
this.check_trait_item(
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
|n, s| MethodNotMemberOfTrait(n, s),
|
||||
|i, s, c| MethodNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
|
||||
visit::walk_assoc_item(
|
||||
@ -1366,6 +1369,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
_,
|
||||
_,
|
||||
)) => {
|
||||
debug!("resolve_implementation AssocItemKind::TyAlias");
|
||||
// We also need a new scope for the impl item type parameters.
|
||||
this.with_generic_param_rib(
|
||||
generics,
|
||||
@ -1375,9 +1379,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
// exists in trait
|
||||
this.check_trait_item(
|
||||
item.ident,
|
||||
&item.kind,
|
||||
TypeNS,
|
||||
item.span,
|
||||
|n, s| TypeNotMemberOfTrait(n, s),
|
||||
|i, s, c| TypeNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
|
||||
visit::walk_assoc_item(
|
||||
@ -1401,9 +1406,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
});
|
||||
}
|
||||
|
||||
fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err: F)
|
||||
where
|
||||
F: FnOnce(Symbol, &str) -> ResolutionError<'_>,
|
||||
fn check_trait_item<F>(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
kind: &AssocItemKind,
|
||||
ns: Namespace,
|
||||
span: Span,
|
||||
err: F,
|
||||
) where
|
||||
F: FnOnce(Ident, &str, Option<Symbol>) -> ResolutionError<'_>,
|
||||
{
|
||||
// If there is a TraitRef in scope for an impl, then the method must be in the
|
||||
// trait.
|
||||
@ -1420,8 +1431,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
let candidate = self.find_similarly_named_assoc_item(ident.name, kind);
|
||||
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
|
||||
self.report_error(span, err(ident.name, &path_names_to_string(path)));
|
||||
self.report_error(span, err(ident, &path_names_to_string(path), candidate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ use crate::{PathResult, PathSource, Segment};
|
||||
|
||||
use rustc_ast::visit::FnKind;
|
||||
use rustc_ast::{
|
||||
self as ast, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, NodeId, Path, Ty,
|
||||
TyKind,
|
||||
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
|
||||
NodeId, Path, Ty, TyKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust::path_segment_to_string;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -1150,6 +1150,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||
true
|
||||
}
|
||||
|
||||
/// Given the target `ident` and `kind`, search for the similarly named associated item
|
||||
/// in `self.current_trait_ref`.
|
||||
crate fn find_similarly_named_assoc_item(
|
||||
&mut self,
|
||||
ident: Symbol,
|
||||
kind: &AssocItemKind,
|
||||
) -> Option<Symbol> {
|
||||
let module = if let Some((module, _)) = self.current_trait_ref {
|
||||
module
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
if ident == kw::Underscore {
|
||||
// We do nothing for `_`.
|
||||
return None;
|
||||
}
|
||||
|
||||
let resolutions = self.r.resolutions(module);
|
||||
let targets = resolutions
|
||||
.borrow()
|
||||
.iter()
|
||||
.filter_map(|(key, res)| res.borrow().binding.map(|binding| (key, binding.res())))
|
||||
.filter(|(_, res)| match (kind, res) {
|
||||
(AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
|
||||
(AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
|
||||
(AssocItemKind::TyAlias(..), Res::Def(DefKind::AssocTy, _)) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|(key, _)| key.ident.name)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
find_best_match_for_name(&targets, ident, None)
|
||||
}
|
||||
|
||||
fn lookup_assoc_candidate<FilterFn>(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
|
@ -206,11 +206,11 @@ enum ResolutionError<'a> {
|
||||
/// parameter list.
|
||||
NameAlreadyUsedInParameterList(Symbol, Span),
|
||||
/// Error E0407: method is not a member of trait.
|
||||
MethodNotMemberOfTrait(Symbol, &'a str),
|
||||
MethodNotMemberOfTrait(Ident, &'a str, Option<Symbol>),
|
||||
/// Error E0437: type is not a member of trait.
|
||||
TypeNotMemberOfTrait(Symbol, &'a str),
|
||||
TypeNotMemberOfTrait(Ident, &'a str, Option<Symbol>),
|
||||
/// Error E0438: const is not a member of trait.
|
||||
ConstNotMemberOfTrait(Symbol, &'a str),
|
||||
ConstNotMemberOfTrait(Ident, &'a str, Option<Symbol>),
|
||||
/// Error E0408: variable `{}` is not bound in all patterns.
|
||||
VariableNotBoundInPattern(&'a BindingError),
|
||||
/// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm.
|
||||
|
@ -356,6 +356,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let callee_ty = self.resolve_vars_if_possible(callee_ty);
|
||||
let mut err = type_error_struct!(
|
||||
self.tcx.sess,
|
||||
callee_expr.span,
|
||||
|
@ -1303,6 +1303,11 @@ impl Clone for BorrowRef<'_> {
|
||||
///
|
||||
/// See the [module-level documentation](self) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(
|
||||
not(bootstrap),
|
||||
must_not_suspend = "Holding a Ref across suspend \
|
||||
points can cause BorrowErrors"
|
||||
)]
|
||||
pub struct Ref<'b, T: ?Sized + 'b> {
|
||||
value: &'b T,
|
||||
borrow: BorrowRef<'b>,
|
||||
@ -1679,6 +1684,11 @@ impl<'b> BorrowRefMut<'b> {
|
||||
///
|
||||
/// See the [module-level documentation](self) for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(
|
||||
not(bootstrap),
|
||||
must_not_suspend = "Holding a RefMut across suspend \
|
||||
points can cause BorrowErrors"
|
||||
)]
|
||||
pub struct RefMut<'b, T: ?Sized + 'b> {
|
||||
value: &'b mut T,
|
||||
borrow: BorrowRefMut<'b>,
|
||||
|
@ -142,6 +142,7 @@
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(min_specialization)]
|
||||
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(no_core)]
|
||||
|
@ -297,6 +297,7 @@
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
#![feature(min_specialization)]
|
||||
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
|
||||
#![feature(needs_panic_runtime)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
|
@ -188,6 +188,12 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
|
||||
/// [`lock`]: Mutex::lock
|
||||
/// [`try_lock`]: Mutex::try_lock
|
||||
#[must_use = "if unused the Mutex will immediately unlock"]
|
||||
#[cfg_attr(
|
||||
not(bootstrap),
|
||||
must_not_suspend = "Holding a MutexGuard across suspend \
|
||||
points can cause deadlocks, delays, \
|
||||
and cause Futures to not implement `Send`"
|
||||
)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct MutexGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a Mutex<T>,
|
||||
|
@ -95,6 +95,12 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
|
||||
/// [`read`]: RwLock::read
|
||||
/// [`try_read`]: RwLock::try_read
|
||||
#[must_use = "if unused the RwLock will immediately unlock"]
|
||||
#[cfg_attr(
|
||||
not(bootstrap),
|
||||
must_not_suspend = "Holding a RwLockReadGuard across suspend \
|
||||
points can cause deadlocks, delays, \
|
||||
and cause Futures to not implement `Send`"
|
||||
)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
@ -115,6 +121,12 @@ unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
|
||||
/// [`write`]: RwLock::write
|
||||
/// [`try_write`]: RwLock::try_write
|
||||
#[must_use = "if unused the RwLock will immediately unlock"]
|
||||
#[cfg_attr(
|
||||
not(bootstrap),
|
||||
must_not_suspend = "Holding a RwLockWriteGuard across suspend \
|
||||
points can cause deadlocks, delays, \
|
||||
and cause Future's to not implement `Send`"
|
||||
)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
|
@ -338,8 +338,17 @@ pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||
}
|
||||
|
||||
Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
|
||||
} else if #[cfg(target_os = "haiku")] {
|
||||
let mut sinfo: libc::system_info = crate::mem::zeroed();
|
||||
let res = libc::get_system_info(&mut sinfo);
|
||||
|
||||
if res != libc::B_OK {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(unsafe { NonZeroUsize::new_unchecked(sinfo.cpu_count as usize) })
|
||||
} else {
|
||||
// FIXME: implement on vxWorks, Redox, Haiku, l4re
|
||||
// FIXME: implement on vxWorks, Redox, l4re
|
||||
Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform"))
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,5 @@ bench-stage = 0
|
||||
incremental = true
|
||||
|
||||
[llvm]
|
||||
# Will download LLVM from CI if available on your platform (Linux only for now)
|
||||
# https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms
|
||||
# Will download LLVM from CI if available on your platform.
|
||||
download-ci-llvm = "if-available"
|
||||
|
@ -11,7 +11,7 @@ trait Sized {}
|
||||
auto trait Freeze {}
|
||||
|
||||
#[lang = "start"]
|
||||
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@ error[E0407]: method `b` is not a member of trait `Foo`
|
||||
--> $DIR/E0407.rs:9:5
|
||||
|
|
||||
LL | fn b() {}
|
||||
| ^^^^^^^^^ not a member of trait `Foo`
|
||||
| ^^^-^^^^^
|
||||
| | |
|
||||
| | help: there is an associated function with a similar name: `a`
|
||||
| not a member of trait `Foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,10 @@ error[E0407]: method `method` is not a member of trait `Tr`
|
||||
--> $DIR/assoc_item_ctxt.rs:35:13
|
||||
|
|
||||
LL | fn method() {}
|
||||
| ^^^^^^^^^^^^^^ not a member of trait `Tr`
|
||||
| ^^^------^^^^^
|
||||
| | |
|
||||
| | help: there is an associated function with a similar name: `method`
|
||||
| not a member of trait `Tr`
|
||||
...
|
||||
LL | mac_trait_impl!();
|
||||
| ------------------ in this macro invocation
|
||||
|
@ -1,9 +1,8 @@
|
||||
// Checks whether declaring a lang item with the wrong number
|
||||
// of generic arguments crashes the compiler (issue #83893, #87573, and part of #9307).
|
||||
// Checks that declaring a lang item with the wrong number
|
||||
// of generic arguments errors rather than crashing (issue #83893, #87573, part of #9307, #79559).
|
||||
|
||||
#![feature(lang_items, no_core)]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait MySized {}
|
||||
@ -26,6 +25,14 @@ struct MyPhantomData<T, U>;
|
||||
//~^ ERROR parameter `T` is never used
|
||||
//~| ERROR parameter `U` is never used
|
||||
|
||||
// When the `start` lang item is missing generics very odd things can happen, especially when
|
||||
// it comes to cross-crate monomorphization
|
||||
#[lang = "start"]
|
||||
//~^ ERROR `start` language item must be applied to a function with 1 generic argument [E0718]
|
||||
fn start(_: *const u8, _: isize, _: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
fn ice() {
|
||||
// Use add
|
||||
let r = 5;
|
||||
@ -42,3 +49,6 @@ fn ice() {
|
||||
// Use phantomdata
|
||||
let _ = MyPhantomData::<(), i32>;
|
||||
}
|
||||
|
||||
// use `start`
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0718]: `add` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:11:1
|
||||
--> $DIR/lang-item-generic-requirements.rs:10:1
|
||||
|
|
||||
LL | #[lang = "add"]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | trait MyAdd<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments
|
||||
|
||||
error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:15:1
|
||||
--> $DIR/lang-item-generic-requirements.rs:14:1
|
||||
|
|
||||
LL | #[lang = "drop_in_place"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -16,7 +16,7 @@ LL | fn my_ptr_drop() {}
|
||||
| - this function has 0 generic arguments
|
||||
|
||||
error[E0718]: `index` language item must be applied to a trait with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:19:1
|
||||
--> $DIR/lang-item-generic-requirements.rs:18:1
|
||||
|
|
||||
LL | #[lang = "index"]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -24,7 +24,7 @@ LL | trait MyIndex<'a, T> {}
|
||||
| ------- this trait has 2 generic arguments
|
||||
|
||||
error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:23:1
|
||||
--> $DIR/lang-item-generic-requirements.rs:22:1
|
||||
|
|
||||
LL | #[lang = "phantom_data"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -32,8 +32,17 @@ LL |
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ------ this struct has 2 generic arguments
|
||||
|
||||
error[E0718]: `start` language item must be applied to a function with 1 generic argument
|
||||
--> $DIR/lang-item-generic-requirements.rs:30:1
|
||||
|
|
||||
LL | #[lang = "start"]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize {
|
||||
| - this function has 0 generic arguments
|
||||
|
||||
error[E0392]: parameter `T` is never used
|
||||
--> $DIR/lang-item-generic-requirements.rs:25:22
|
||||
--> $DIR/lang-item-generic-requirements.rs:24:22
|
||||
|
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ^ unused parameter
|
||||
@ -42,7 +51,7 @@ LL | struct MyPhantomData<T, U>;
|
||||
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
|
||||
|
||||
error[E0392]: parameter `U` is never used
|
||||
--> $DIR/lang-item-generic-requirements.rs:25:25
|
||||
--> $DIR/lang-item-generic-requirements.rs:24:25
|
||||
|
|
||||
LL | struct MyPhantomData<T, U>;
|
||||
| ^ unused parameter
|
||||
@ -50,7 +59,7 @@ LL | struct MyPhantomData<T, U>;
|
||||
= help: consider removing `U` or referring to it in a field
|
||||
= help: if you intended `U` to be a const parameter, use `const U: usize` instead
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0392, E0718.
|
||||
For more information about an error, try `rustc --explain E0392`.
|
||||
|
12
src/test/ui/lint/must_not_suspend/mutex.rs
Normal file
12
src/test/ui/lint/must_not_suspend/mutex.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// edition:2018
|
||||
#![deny(must_not_suspend)]
|
||||
|
||||
async fn other() {}
|
||||
|
||||
pub async fn uhoh(m: std::sync::Mutex<()>) {
|
||||
let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across
|
||||
other().await;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
26
src/test/ui/lint/must_not_suspend/mutex.stderr
Normal file
26
src/test/ui/lint/must_not_suspend/mutex.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: `MutexGuard` held across a suspend point, but should not be
|
||||
--> $DIR/mutex.rs:7:9
|
||||
|
|
||||
LL | let _guard = m.lock().unwrap();
|
||||
| ^^^^^^
|
||||
LL | other().await;
|
||||
| ------------- the value is held across this suspend point
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/mutex.rs:2:9
|
||||
|
|
||||
LL | #![deny(must_not_suspend)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
|
||||
--> $DIR/mutex.rs:7:9
|
||||
|
|
||||
LL | let _guard = m.lock().unwrap();
|
||||
| ^^^^^^
|
||||
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
|
||||
--> $DIR/mutex.rs:7:9
|
||||
|
|
||||
LL | let _guard = m.lock().unwrap();
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
16
src/test/ui/suggestions/issue-88730.rs
Normal file
16
src/test/ui/suggestions/issue-88730.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![allow(unused, nonstandard_style)]
|
||||
#![deny(bindings_with_variant_name)]
|
||||
|
||||
// If an enum has two different variants,
|
||||
// then it cannot be matched upon in a function argument.
|
||||
// It still gets a warning, but no suggestions.
|
||||
enum Foo {
|
||||
C,
|
||||
D,
|
||||
}
|
||||
|
||||
fn foo(C: Foo) {} //~ERROR
|
||||
|
||||
fn main() {
|
||||
let C = Foo::D; //~ERROR
|
||||
}
|
21
src/test/ui/suggestions/issue-88730.stderr
Normal file
21
src/test/ui/suggestions/issue-88730.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo`
|
||||
--> $DIR/issue-88730.rs:12:8
|
||||
|
|
||||
LL | fn foo(C: Foo) {}
|
||||
| ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-88730.rs:2:9
|
||||
|
|
||||
LL | #![deny(bindings_with_variant_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo`
|
||||
--> $DIR/issue-88730.rs:15:9
|
||||
|
|
||||
LL | let C = Foo::D;
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0170`.
|
48
src/test/ui/suggestions/suggest-trait-items.rs
Normal file
48
src/test/ui/suggestions/suggest-trait-items.rs
Normal file
@ -0,0 +1,48 @@
|
||||
trait Foo {
|
||||
type Type;
|
||||
|
||||
fn foo();
|
||||
fn bar();
|
||||
fn qux();
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl Foo for A {
|
||||
//~^ ERROR not all trait items implemented
|
||||
type Typ = ();
|
||||
//~^ ERROR type `Typ` is not a member of trait
|
||||
//~| HELP there is an associated type with a similar name
|
||||
|
||||
fn fooo() {}
|
||||
//~^ ERROR method `fooo` is not a member of trait
|
||||
//~| HELP there is an associated function with a similar name
|
||||
|
||||
fn barr() {}
|
||||
//~^ ERROR method `barr` is not a member of trait
|
||||
//~| HELP there is an associated function with a similar name
|
||||
|
||||
fn quux() {}
|
||||
//~^ ERROR method `quux` is not a member of trait
|
||||
//~| HELP there is an associated function with a similar name
|
||||
}
|
||||
//~^ HELP implement the missing item
|
||||
//~| HELP implement the missing item
|
||||
//~| HELP implement the missing item
|
||||
//~| HELP implement the missing item
|
||||
|
||||
trait Bar {
|
||||
const Const: i32;
|
||||
}
|
||||
|
||||
struct B;
|
||||
|
||||
impl Bar for B {
|
||||
//~^ ERROR not all trait items implemented
|
||||
const Cnst: i32 = 0;
|
||||
//~^ ERROR const `Cnst` is not a member of trait
|
||||
//~| HELP there is an associated constant with a similar name
|
||||
}
|
||||
//~^ HELP implement the missing item
|
||||
|
||||
fn main() {}
|
74
src/test/ui/suggestions/suggest-trait-items.stderr
Normal file
74
src/test/ui/suggestions/suggest-trait-items.stderr
Normal file
@ -0,0 +1,74 @@
|
||||
error[E0437]: type `Typ` is not a member of trait `Foo`
|
||||
--> $DIR/suggest-trait-items.rs:13:5
|
||||
|
|
||||
LL | type Typ = ();
|
||||
| ^^^^^---^^^^^^
|
||||
| | |
|
||||
| | help: there is an associated type with a similar name: `Type`
|
||||
| not a member of trait `Foo`
|
||||
|
||||
error[E0407]: method `fooo` is not a member of trait `Foo`
|
||||
--> $DIR/suggest-trait-items.rs:17:5
|
||||
|
|
||||
LL | fn fooo() {}
|
||||
| ^^^----^^^^^
|
||||
| | |
|
||||
| | help: there is an associated function with a similar name: `foo`
|
||||
| not a member of trait `Foo`
|
||||
|
||||
error[E0407]: method `barr` is not a member of trait `Foo`
|
||||
--> $DIR/suggest-trait-items.rs:21:5
|
||||
|
|
||||
LL | fn barr() {}
|
||||
| ^^^----^^^^^
|
||||
| | |
|
||||
| | help: there is an associated function with a similar name: `bar`
|
||||
| not a member of trait `Foo`
|
||||
|
||||
error[E0407]: method `quux` is not a member of trait `Foo`
|
||||
--> $DIR/suggest-trait-items.rs:25:5
|
||||
|
|
||||
LL | fn quux() {}
|
||||
| ^^^----^^^^^
|
||||
| | |
|
||||
| | help: there is an associated function with a similar name: `qux`
|
||||
| not a member of trait `Foo`
|
||||
|
||||
error[E0438]: const `Cnst` is not a member of trait `Bar`
|
||||
--> $DIR/suggest-trait-items.rs:42:5
|
||||
|
|
||||
LL | const Cnst: i32 = 0;
|
||||
| ^^^^^^----^^^^^^^^^^
|
||||
| | |
|
||||
| | help: there is an associated constant with a similar name: `Const`
|
||||
| not a member of trait `Bar`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux`
|
||||
--> $DIR/suggest-trait-items.rs:11:1
|
||||
|
|
||||
LL | type Type;
|
||||
| ---------- `Type` from trait
|
||||
LL |
|
||||
LL | fn foo();
|
||||
| --------- `foo` from trait
|
||||
LL | fn bar();
|
||||
| --------- `bar` from trait
|
||||
LL | fn qux();
|
||||
| --------- `qux` from trait
|
||||
...
|
||||
LL | impl Foo for A {
|
||||
| ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `Const`
|
||||
--> $DIR/suggest-trait-items.rs:40:1
|
||||
|
|
||||
LL | const Const: i32;
|
||||
| ----------------- `Const` from trait
|
||||
...
|
||||
LL | impl Bar for B {
|
||||
| ^^^^^^^^^^^^^^ missing `Const` in implementation
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0407, E0437, E0438.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
3
src/test/ui/typeck/call-block.rs
Normal file
3
src/test/ui/typeck/call-block.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
let _ = {42}(); //~ ERROR expected function, found `{integer}`
|
||||
}
|
11
src/test/ui/typeck/call-block.stderr
Normal file
11
src/test/ui/typeck/call-block.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0618]: expected function, found `{integer}`
|
||||
--> $DIR/call-block.rs:2:13
|
||||
|
|
||||
LL | let _ = {42}();
|
||||
| ^^^^--
|
||||
| |
|
||||
| call expression requires function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0618`.
|
@ -15,11 +15,12 @@ pub trait Copy {}
|
||||
pub unsafe trait Freeze {}
|
||||
|
||||
#[lang = "start"]
|
||||
#[start]
|
||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct A;
|
||||
|
||||
impl A {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
|
||||
--> $DIR/def_id_nocore.rs:26:19
|
||||
--> $DIR/def_id_nocore.rs:27:19
|
||||
|
|
||||
LL | pub fn as_ref(self) -> &'static str {
|
||||
| ^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user