Auto merge of #94548 - matthiaskrgr:rollup-spa38z8, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #93562 (Update the documentation for `{As,Into,From}Raw{Fd,Handle,Socket}`.)
 - #94101 (rustdoc: add test cases for hidden enum variants)
 - #94484 (8 - Make more use of `let_chains`)
 - #94522 (Remove out-of-context line at end of E0284 message)
 - #94534 (Re-export (unstable) core::ffi types from std::ffi)
 - #94536 (Move transmute_undefined_repr back to nursery again)
 - #94537 (Use ? operator in one instance instead of manual match)
 - #94544 (Add some examples to comments in mbe code)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-03-03 10:14:04 +00:00
commit 06460fe72c
25 changed files with 360 additions and 310 deletions

View File

@ -30,5 +30,3 @@ fn main() {
d = d + m;
}
```
Note that the type of `v` can now be inferred from the type of `temp`.

View File

@ -345,6 +345,38 @@ fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 't
/// token tree. The depth of the `NamedMatch` structure will therefore depend
/// only on the nesting depth of `ast::TTSeq`s in the originating
/// token tree it was derived from.
///
/// In layman's terms: `NamedMatch` will form a tree representing nested matches of a particular
/// meta variable. For example, if we are matching the following macro against the following
/// invocation...
///
/// ```rust
/// macro_rules! foo {
/// ($($($x:ident),+);+) => {}
/// }
///
/// foo!(a, b, c, d; a, b, c, d, e);
/// ```
///
/// Then, the tree will have the following shape:
///
/// ```rust
/// MatchedSeq([
/// MatchedSeq([
/// MatchedNonterminal(a),
/// MatchedNonterminal(b),
/// MatchedNonterminal(c),
/// MatchedNonterminal(d),
/// ]),
/// MatchedSeq([
/// MatchedNonterminal(a),
/// MatchedNonterminal(b),
/// MatchedNonterminal(c),
/// MatchedNonterminal(d),
/// MatchedNonterminal(e),
/// ])
/// ])
/// ```
#[derive(Debug, Clone)]
crate enum NamedMatch {
MatchedSeq(Lrc<NamedMatchVec>),

View File

@ -358,6 +358,12 @@ impl LockstepIterSize {
/// Note that if `repeats` does not match the exact correct depth of a meta-var,
/// `lookup_cur_matched` will return `None`, which is why this still works even in the presence of
/// multiple nested matcher sequences.
///
/// Example: `$($($x $y)+*);+` -- we need to make sure that `x` and `y` repeat the same amount as
/// each other at the given depth when the macro was invoked. If they don't it might mean they were
/// declared at unequal depths or there was a compile bug. For example, if we have 3 repetitions of
/// the outer sequence and 4 repetitions of the inner sequence for `x`, we should have the same for
/// `y`; otherwise, we can't transcribe them both at the given depth.
fn lockstep_iter_size(
tree: &mbe::TokenTree,
interpolations: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,

View File

@ -606,17 +606,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// don't show type `_`
err.span_label(span, format!("this expression has type `{}`", ty));
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
if ty.is_box() && ty.boxed_ty() == found {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
}
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
&& ty.is_box() && ty.boxed_ty() == found
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
}
}
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
@ -1748,13 +1747,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.check_and_note_conflicting_crates(diag, terr);
self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
if let Some(def_id) = def_id.as_local() {
let span = self.tcx.def_span(def_id);
diag.span_note(span, "this closure does not fulfill the lifetime requirements");
}
}
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
&& let Some(def_id) = def_id.as_local()
{
let span = self.tcx.def_span(def_id);
diag.span_note(span, "this closure does not fulfill the lifetime requirements");
}
// It reads better to have the error origin as the final
@ -2046,19 +2044,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// containing a single character, perhaps the user meant to write `'c'` to
// specify a character literal (issue #92479)
(ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
if let Some(code) =
code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
{
if code.chars().count() == 1 {
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
Applicability::MachineApplicable,
);
}
}
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
&& code.chars().count() == 1
{
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
Applicability::MachineApplicable,
);
}
}
// If a string was expected and the found expression is a character literal,
@ -2080,18 +2075,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => {}
}
}
if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
*trace.cause.code()
let code = trace.cause.code();
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
&& let hir::MatchSource::TryDesugar = source
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values)
{
if let hir::MatchSource::TryDesugar = source {
if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
err.note(&format!(
"`?` operator cannot convert from `{}` to `{}`",
found_ty.content(),
expected_ty.content(),
));
}
}
err.note(&format!(
"`?` operator cannot convert from `{}` to `{}`",
found_ty.content(),
expected_ty.content(),
));
}
err
}

View File

@ -114,28 +114,25 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind {
if let Some(pat) = arm.pat.for_loop_some() {
if let Some(ty) = self.node_ty_contains_target(pat.hir_id) {
self.found_for_loop_iter = Some(scrutinee);
self.found_node_ty = Some(ty);
return;
}
}
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind
&& let Some(pat) = arm.pat.for_loop_some()
&& let Some(ty) = self.node_ty_contains_target(pat.hir_id)
{
self.found_for_loop_iter = Some(scrutinee);
self.found_node_ty = Some(ty);
return;
}
if let ExprKind::MethodCall(segment, exprs, _) = expr.kind {
if segment.ident.span == self.target_span
&& Some(self.target)
== self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
typeck_results
.borrow()
.node_type_opt(exprs.first().unwrap().hir_id)
.map(Into::into)
})
{
self.found_exact_method_call = Some(&expr);
return;
}
if let ExprKind::MethodCall(segment, exprs, _) = expr.kind
&& segment.ident.span == self.target_span
&& Some(self.target) == self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
typeck_results
.borrow()
.node_type_opt(exprs.first().unwrap().hir_id)
.map(Into::into)
})
{
self.found_exact_method_call = Some(&expr);
return;
}
// FIXME(const_generics): Currently, any uninferred `const` generics arguments
@ -602,10 +599,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
let use_diag = local_visitor.found_use_diagnostic.as_ref();
if let Some(use_diag) = use_diag {
if use_diag.applies_to(err_span) {
use_diag.attach_note(&mut err);
}
if let Some(use_diag) = use_diag && use_diag.applies_to(err_span) {
use_diag.attach_note(&mut err);
}
let param_type = arg_data.kind.descr();
@ -736,29 +731,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
// |
// = note: cannot satisfy `Impl: Into<_>`
if !impl_candidates.is_empty() && e.span.contains(span) {
if let Some(expr) = exprs.first() {
if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
if let [path_segment] = path.segments {
let candidate_len = impl_candidates.len();
let suggestions = impl_candidates.iter().map(|candidate| {
format!(
"{}::{}({})",
candidate, segment.ident, path_segment.ident
)
});
err.span_suggestions(
e.span,
&format!(
"use the fully qualified path for the potential candidate{}",
pluralize!(candidate_len),
),
suggestions,
Applicability::MaybeIncorrect,
);
}
}
};
if !impl_candidates.is_empty() && e.span.contains(span)
&& let Some(expr) = exprs.first()
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
&& let [path_segment] = path.segments
{
let candidate_len = impl_candidates.len();
let suggestions = impl_candidates.iter().map(|candidate| {
format!(
"{}::{}({})",
candidate, segment.ident, path_segment.ident
)
});
err.span_suggestions(
e.span,
&format!(
"use the fully qualified path for the potential candidate{}",
pluralize!(candidate_len),
),
suggestions,
Applicability::MaybeIncorrect,
);
}
// Suggest specifying type params or point out the return type of the call:
//

View File

@ -223,35 +223,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
let mut override_error_code = None;
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
// Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
// `'static` lifetime when called as a method on a binding: `bar.qux()`.
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
override_error_code = Some(ctxt.assoc_item.name);
}
}
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin
&& let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code()
// Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
// `'static` lifetime when called as a method on a binding: `bar.qux()`.
&& self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
{
override_error_code = Some(ctxt.assoc_item.name);
}
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
let code = match cause.code() {
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin
&& let code = match cause.code() {
ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
_ => cause.code(),
};
if let (ObligationCauseCode::ItemObligation(item_def_id), None) =
(code, override_error_code)
}
&& let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
{
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
// lifetime as above, but called using a fully-qualified path to the method:
// `Foo::qux(bar)`.
let mut v = TraitObjectVisitor(FxHashSet::default());
v.visit_ty(param.param_ty);
if let Some((ident, self_ty)) =
self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0)
&& self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
{
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
// lifetime as above, but called using a fully-qualified path to the method:
// `Foo::qux(bar)`.
let mut v = TraitObjectVisitor(FxHashSet::default());
v.visit_ty(param.param_ty);
if let Some((ident, self_ty)) =
self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0)
{
if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) {
override_error_code = Some(ident.name);
}
}
override_error_code = Some(ident.name);
}
}
if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {

View File

@ -23,51 +23,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let error = self.error.as_ref()?;
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict(
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
_, var_origin, sub_origin, _sub, sup_origin, _sup, _,
) = error.clone()
&& let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
&& let (
sub_expected_found @ Some((sub_expected, sub_found)),
sup_expected_found @ Some(_),
CompareImplMethodObligation { trait_item_def_id, .. },
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
&& sup_expected_found == sub_expected_found
{
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
if let (
sub_expected_found @ Some((sub_expected, sub_found)),
sup_expected_found @ Some(_),
CompareImplMethodObligation { trait_item_def_id, .. },
) = (&sub_trace.values.ty(), &sup_trace.values.ty(), sub_trace.cause.code())
{
if sup_expected_found == sub_expected_found {
self.emit_err(
var_origin.span(),
*sub_expected,
*sub_found,
*trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
}
}
self.emit_err(
var_origin.span(),
sub_expected,
sub_found,
*trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
if let RegionResolutionError::ConcreteFailure(origin, _, _)
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
{
if let SubregionOrigin::CompareImplTypeObligation {
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
&& let SubregionOrigin::CompareImplTypeObligation {
span,
impl_item_def_id,
trait_item_def_id,
} = origin
{
self.emit_associated_type_err(
span,
self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id,
trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
{
self.emit_associated_type_err(
span,
self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id,
trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
None
}

View File

@ -220,12 +220,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReVar(vid) = *r {
if self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
}
if let ty::ReVar(vid) = *r && self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
}
r
}

View File

@ -304,10 +304,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// check below for a common case, here purely as an
// optimization.
let b_universe = self.var_infos[b_vid].universe;
if let ReEmpty(a_universe) = *a_region {
if a_universe == b_universe {
return false;
}
if let ReEmpty(a_universe) = *a_region && a_universe == b_universe {
return false;
}
let mut lub = self.lub_concrete_regions(a_region, cur_region);
@ -324,10 +322,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// tighter bound than `'static`.
//
// (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
if let ty::RePlaceholder(p) = *lub {
if b_universe.cannot_name(p.universe) {
lub = self.tcx().lifetimes.re_static;
}
if let ty::RePlaceholder(p) = *lub && b_universe.cannot_name(p.universe) {
lub = self.tcx().lifetimes.re_static;
}
debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);

View File

@ -963,10 +963,8 @@ where
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("TypeGeneralizer::regions(a={:?})", a);
if let ty::ReLateBound(debruijn, _) = *a {
if debruijn < self.first_free_index {
return Ok(a);
}
if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index {
return Ok(a);
}
// For now, we just always create a fresh region variable to

View File

@ -470,10 +470,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
debug!("RegionConstraintCollector: add_verify({:?})", verify);
// skip no-op cases known to be satisfied
if let VerifyBound::AllBounds(ref bs) = verify.bound {
if bs.is_empty() {
return;
}
if let VerifyBound::AllBounds(ref bs) = verify.bound && bs.is_empty() {
return;
}
let index = self.data.verifys.len();

View File

@ -12,18 +12,19 @@
//!
//! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(derive_default_enum)]
#![feature(extend_one)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(control_flow_enum)]
#![feature(min_specialization)]
#![feature(label_break_value)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(never_type)]
#![recursion_limit = "512"] // For rustdoc
#![allow(rustc::potential_query_instability)]
#[macro_use]
extern crate rustc_macros;

View File

@ -60,12 +60,10 @@ pub fn report_object_safety_error<'tcx>(
let mut multi_span = vec![];
let mut messages = vec![];
for violation in violations {
if let ObjectSafetyViolation::SizedSelf(sp) = &violation {
if !sp.is_empty() {
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
// with a `Span`.
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
}
if let ObjectSafetyViolation::SizedSelf(sp) = &violation && !sp.is_empty() {
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
// with a `Span`.
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
}
if reported_violations.insert(violation.clone()) {
let spans = violation.spans();

View File

@ -159,6 +159,15 @@ pub use self::os_str::{OsStr, OsString};
#[stable(feature = "core_c_void", since = "1.30.0")]
pub use core::ffi::c_void;
#[unstable(feature = "core_ffi_c", issue = "94501")]
pub use core::ffi::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
c_ulong, c_ulonglong, c_ushort,
};
#[unstable(feature = "c_size_t", issue = "88345")]
pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t};
#[unstable(
feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \

View File

@ -261,6 +261,7 @@
#![feature(const_socketaddr)]
#![feature(const_trait_impl)]
#![feature(container_error_extra)]
#![feature(c_size_t)]
#![feature(core_ffi_c)]
#![feature(core_intrinsics)]
#![feature(core_panic)]

View File

@ -5,6 +5,8 @@
use crate::fs;
use crate::io;
use crate::os::raw;
#[cfg(doc)]
use crate::os::unix::io::AsFd;
#[cfg(unix)]
use crate::os::unix::io::OwnedFd;
#[cfg(target_os = "wasi")]
@ -24,9 +26,14 @@ pub type RawFd = raw::c_int;
pub trait AsRawFd {
/// Extracts the raw file descriptor.
///
/// This method does **not** pass ownership of the raw file descriptor
/// to the caller. The descriptor is only guaranteed to be valid while
/// the original object has not yet been destroyed.
/// This function is typically used to **borrow** an owned file descriptor.
/// When used in this way, this method does **not** pass ownership of the
/// raw file descriptor to the caller, and the file descriptor is only
/// guaranteed to be valid while the original object has not yet been
/// destroyed.
///
/// However, borrowing is not strictly required. See [`AsFd::as_fd`]
/// for an API which strictly borrows a file descriptor.
///
/// # Example
///
@ -55,15 +62,18 @@ pub trait FromRawFd {
/// Constructs a new instance of `Self` from the given raw file
/// descriptor.
///
/// This function **consumes ownership** of the specified file
/// descriptor. The returned object will take responsibility for closing
/// it when the object goes out of scope.
/// This function is typically used to **consume ownership** of the
/// specified file descriptor. When used in this way, the returned object
/// will take responsibility for closing it when the object goes out of
/// scope.
///
/// This function is also unsafe as the primitives currently returned
/// have the contract that they are the sole owner of the file
/// descriptor they are wrapping. Usage of this function could
/// accidentally allow violating this contract which can cause memory
/// unsafety in code that relies on it being true.
/// However, consuming ownership is not strictly required. Use a
/// [`From<OwnedFd>::from`] implementation for an API which strictly
/// consumes ownership.
///
/// # Safety
///
/// The `fd` passed in must be a valid an open file descriptor.
///
/// # Example
///
@ -94,9 +104,13 @@ pub trait FromRawFd {
pub trait IntoRawFd {
/// Consumes this object, returning the raw underlying file descriptor.
///
/// This function **transfers ownership** of the underlying file descriptor
/// to the caller. Callers are then the unique owners of the file descriptor
/// and must close the descriptor once it's no longer needed.
/// This function is typically used to **transfer ownership** of the underlying
/// file descriptor to the caller. When used in this way, callers are then the unique
/// owners of the file descriptor and must close it once it's no longer needed.
///
/// However, transferring ownership is not strictly required. Use a
/// [`Into<OwnedFd>::into`] implementation for an API which strictly
/// transfers ownership.
///
/// # Example
///

View File

@ -214,29 +214,13 @@ impl IntoRawHandle for OwnedHandle {
}
impl FromRawHandle for OwnedHandle {
/// Constructs a new instance of `Self` from the given raw handle.
///
/// # Safety
///
/// The resource pointed to by `handle` must be open and suitable for
/// assuming ownership. The resource must not require any cleanup other
/// than `CloseHandle`.
///
/// In particular, it must not be used with handles to open registry
/// keys which need to be closed with [`RegCloseKey`] instead.
///
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
/// sometimes a valid handle value. See [here] for the full story.
///
/// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
#[inline]
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self { handle }
}
}
impl FromRawHandle for HandleOrNull {
impl HandleOrNull {
/// Constructs a new instance of `Self` from the given `RawHandle` returned
/// from a Windows API that uses null to indicate failure, such as
/// `CreateThread`.
@ -246,18 +230,18 @@ impl FromRawHandle for HandleOrNull {
///
/// # Safety
///
/// The resource pointed to by `handle` must be either open and otherwise
/// unowned, or null. Note that not all Windows APIs use null for errors;
/// see [here] for the full story.
/// The passed `handle` value must either satisfy the safety requirements
/// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
/// Windows APIs use null for errors; see [here] for the full story.
///
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
#[inline]
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(OwnedHandle::from_raw_handle(handle))
}
}
impl FromRawHandle for HandleOrInvalid {
impl HandleOrInvalid {
/// Constructs a new instance of `Self` from the given `RawHandle` returned
/// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
/// failure, such as `CreateFileW`.
@ -267,14 +251,14 @@ impl FromRawHandle for HandleOrInvalid {
///
/// # Safety
///
/// The resource pointed to by `handle` must be either open and otherwise
/// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not
/// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for
/// the full story.
/// The passed `handle` value must either satisfy the safety requirements
/// of [`FromRawHandle::from_raw_handle`], or be
/// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
/// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
///
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
#[inline]
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(OwnedHandle::from_raw_handle(handle))
}
}

View File

@ -5,6 +5,8 @@
use crate::fs;
use crate::io;
use crate::net;
#[cfg(doc)]
use crate::os::windows::io::{AsHandle, AsSocket};
use crate::os::windows::io::{OwnedHandle, OwnedSocket};
use crate::os::windows::raw;
use crate::sys;
@ -22,7 +24,15 @@ pub type RawSocket = raw::SOCKET;
/// Extracts raw handles.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawHandle {
/// Extracts the raw handle, without taking any ownership.
/// Extracts the raw handle.
///
/// This function is typically used to **borrow** an owned handle.
/// When used in this way, this method does **not** pass ownership of the
/// raw handle to the caller, and the handle is only guaranteed
/// to be valid while the original object has not yet been destroyed.
///
/// However, borrowing is not strictly required. See [`AsHandle::as_handle`]
/// for an API which strictly borrows a handle.
#[stable(feature = "rust1", since = "1.0.0")]
fn as_raw_handle(&self) -> RawHandle;
}
@ -32,15 +42,28 @@ pub trait AsRawHandle {
pub trait FromRawHandle {
/// Constructs a new I/O object from the specified raw handle.
///
/// This function will **consume ownership** of the handle given,
/// passing responsibility for closing the handle to the returned
/// object.
/// This function is typically used to **consume ownership** of the handle
/// given, passing responsibility for closing the handle to the returned
/// object. When used in this way, the returned object
/// will take responsibility for closing it when the object goes out of
/// scope.
///
/// This function is also unsafe as the primitives currently returned
/// have the contract that they are the sole owner of the file
/// descriptor they are wrapping. Usage of this function could
/// accidentally allow violating this contract which can cause memory
/// unsafety in code that relies on it being true.
/// However, consuming ownership is not strictly required. Use a
/// `From<OwnedHandle>::from` implementation for an API which strictly
/// consumes ownership.
///
/// # Safety
///
/// The `handle` passed in must:
/// - be a valid an open handle,
/// - be a handle for a resource that may be freed via [`CloseHandle`]
/// (as opposed to `RegCloseKey` or other close functions).
///
/// Note that the handle *may* have the value `INVALID_HANDLE_VALUE` (-1),
/// which is sometimes a valid handle value. See [here] for the full story.
///
/// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
#[stable(feature = "from_raw_os", since = "1.1.0")]
unsafe fn from_raw_handle(handle: RawHandle) -> Self;
}
@ -51,9 +74,13 @@ pub trait FromRawHandle {
pub trait IntoRawHandle {
/// Consumes this object, returning the raw underlying handle.
///
/// This function **transfers ownership** of the underlying handle to the
/// caller. Callers are then the unique owners of the handle and must close
/// it once it's no longer needed.
/// This function is typically used to **transfer ownership** of the underlying
/// handle to the caller. When used in this way, callers are then the unique
/// owners of the handle and must close it once it's no longer needed.
///
/// However, transferring ownership is not strictly required. Use a
/// `Into<OwnedHandle>::into` implementation for an API which strictly
/// transfers ownership.
#[stable(feature = "into_raw_os", since = "1.4.0")]
fn into_raw_handle(self) -> RawHandle;
}
@ -130,7 +157,15 @@ impl IntoRawHandle for fs::File {
/// Extracts raw sockets.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawSocket {
/// Extracts the underlying raw socket from this object.
/// Extracts the raw socket.
///
/// This function is typically used to **borrow** an owned socket.
/// When used in this way, this method does **not** pass ownership of the
/// raw socket to the caller, and the socket is only guaranteed
/// to be valid while the original object has not yet been destroyed.
///
/// However, borrowing is not strictly required. See [`AsSocket::as_socket`]
/// for an API which strictly borrows a socket.
#[stable(feature = "rust1", since = "1.0.0")]
fn as_raw_socket(&self) -> RawSocket;
}
@ -138,16 +173,25 @@ pub trait AsRawSocket {
/// Creates I/O objects from raw sockets.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawSocket {
/// Creates a new I/O object from the given raw socket.
/// Constructs a new I/O object from the specified raw socket.
///
/// This function will **consume ownership** of the socket provided and
/// it will be closed when the returned object goes out of scope.
/// This function is typically used to **consume ownership** of the socket
/// given, passing responsibility for closing the socket to the returned
/// object. When used in this way, the returned object
/// will take responsibility for closing it when the object goes out of
/// scope.
///
/// This function is also unsafe as the primitives currently returned
/// have the contract that they are the sole owner of the file
/// descriptor they are wrapping. Usage of this function could
/// accidentally allow violating this contract which can cause memory
/// unsafety in code that relies on it being true.
/// However, consuming ownership is not strictly required. Use a
/// `From<OwnedSocket>::from` implementation for an API which strictly
/// consumes ownership.
///
/// # Safety
///
/// The `socket` passed in must:
/// - be a valid an open socket,
/// - be a socket that may be freed via [`closesocket`].
///
/// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket
#[stable(feature = "from_raw_os", since = "1.1.0")]
unsafe fn from_raw_socket(sock: RawSocket) -> Self;
}
@ -158,9 +202,13 @@ pub trait FromRawSocket {
pub trait IntoRawSocket {
/// Consumes this object, returning the raw underlying socket.
///
/// This function **transfers ownership** of the underlying socket to the
/// caller. Callers are then the unique owners of the socket and must close
/// it once it's no longer needed.
/// This function is typically used to **transfer ownership** of the underlying
/// socket to the caller. When used in this way, callers are then the unique
/// owners of the socket and must close it once it's no longer needed.
///
/// However, transferring ownership is not strictly required. Use a
/// `Into<OwnedSocket>::into` implementation for an API which strictly
/// transfers ownership.
#[stable(feature = "into_raw_os", since = "1.4.0")]
fn into_raw_socket(self) -> RawSocket;
}

View File

@ -172,13 +172,6 @@ impl IntoRawSocket for OwnedSocket {
}
impl FromRawSocket for OwnedSocket {
/// Constructs a new instance of `Self` from the given raw socket.
///
/// # Safety
///
/// The resource pointed to by `socket` must be open and suitable for
/// assuming ownership. The resource must not require cleanup other than
/// `closesocket`.
#[inline]
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);

View File

@ -111,58 +111,55 @@ crate fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
let externs = options.externs.clone();
let json_unused_externs = options.json_unused_externs;
let res = interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
let mut global_ctxt = queries.global_ctxt()?.take();
let (tests, unused_extern_reports, compiling_test_count) =
interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
let mut global_ctxt = queries.global_ctxt()?.take();
let collector = global_ctxt.enter(|tcx| {
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let collector = global_ctxt.enter(|tcx| {
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let opts = scrape_test_config(crate_attrs);
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
tcx.crate_name(LOCAL_CRATE),
options,
false,
opts,
Some(compiler.session().parse_sess.clone_source_map()),
None,
enable_per_target_ignores,
);
let opts = scrape_test_config(crate_attrs);
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
tcx.crate_name(LOCAL_CRATE),
options,
false,
opts,
Some(compiler.session().parse_sess.clone_source_map()),
None,
enable_per_target_ignores,
);
let mut hir_collector = HirCollector {
sess: compiler.session(),
collector: &mut collector,
map: tcx.hir(),
codes: ErrorCodes::from(
compiler.session().opts.unstable_features.is_nightly_build(),
),
tcx,
};
hir_collector.visit_testable(
"".to_string(),
CRATE_HIR_ID,
tcx.hir().span(CRATE_HIR_ID),
|this| tcx.hir().walk_toplevel_module(this),
);
let mut hir_collector = HirCollector {
sess: compiler.session(),
collector: &mut collector,
map: tcx.hir(),
codes: ErrorCodes::from(
compiler.session().opts.unstable_features.is_nightly_build(),
),
tcx,
};
hir_collector.visit_testable(
"".to_string(),
CRATE_HIR_ID,
tcx.hir().span(CRATE_HIR_ID),
|this| tcx.hir().walk_toplevel_module(this),
);
collector
});
if compiler.session().diagnostic().has_errors_or_lint_errors() {
FatalError.raise();
}
collector
});
if compiler.session().diagnostic().has_errors_or_lint_errors() {
FatalError.raise();
}
let unused_extern_reports = collector.unused_extern_reports.clone();
let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
let ret: Result<_, ErrorGuaranteed> =
Ok((collector.tests, unused_extern_reports, compiling_test_count));
ret
})
});
let (tests, unused_extern_reports, compiling_test_count) = match res {
Ok(res) => res,
Err(ErrorGuaranteed) => return Err(ErrorGuaranteed),
};
let unused_extern_reports = collector.unused_extern_reports.clone();
let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
let ret: Result<_, ErrorGuaranteed> =
Ok((collector.tests, unused_extern_reports, compiling_test_count));
ret
})
})?;
run_tests(test_args, nocapture, tests);

View File

@ -0,0 +1,9 @@
// @has strip_enum_variant/enum.MyThing.html
// @has - '//code' 'Shown'
// @!has - '//code' 'NotShown'
// @has - '//code' '// some variants omitted'
pub enum MyThing {
Shown,
#[doc(hidden)]
NotShown,
}

View File

@ -281,7 +281,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
LintId::of(transmute::TRANSMUTE_NUM_TO_BYTES),
LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
LintId::of(transmute::WRONG_TRANSMUTE),
LintId::of(transmuting_null::TRANSMUTING_NULL),

View File

@ -58,7 +58,6 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
LintId::of(serde_api::SERDE_API_MISUSE),
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
LintId::of(swap::ALMOST_SWAPPED),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
LintId::of(transmute::WRONG_TRANSMUTE),
LintId::of(transmuting_null::TRANSMUTING_NULL),

View File

@ -26,6 +26,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(strings::STRING_LIT_AS_BYTES),
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::USELESS_TRANSMUTE),
LintId::of(use_self::USE_SELF),
])

View File

@ -377,7 +377,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.60.0"]
pub TRANSMUTE_UNDEFINED_REPR,
correctness,
nursery,
"transmute to or from a type with an undefined representation"
}