diff --git a/compiler/rustc_error_codes/src/error_codes/E0284.md b/compiler/rustc_error_codes/src/error_codes/E0284.md index 82598aeec0215..5a92f8352d2c1 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0284.md +++ b/compiler/rustc_error_codes/src/error_codes/E0284.md @@ -30,5 +30,3 @@ fn main() { d = d + m; } ``` - -Note that the type of `v` can now be inferred from the type of `temp`. diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index dd82add08dd98..a419612e315df 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -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), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 01a7f7266172c..54000527c15b9 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -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, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index edb2b11c0397c..bf4882d459573 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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 } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 8ff0eed71ed03..3bc30f0220d40 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -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: `>::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: // diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a6de0c3d9fb5c..99dd418015b14 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -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()) { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 673c112163e1b..3f0f50bb75af1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -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 } diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index c5c131a5b796b..c5b90f79dc284 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -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 } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index c7b4a96fb7853..0f341a947ad35 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -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); diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 60f776d8c1f67..69db6509b798d 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -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 diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index a5bd3b15c8d8f..6966f5014464e 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -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(); diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 4960630051f3e..08e005364ce64 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -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(label_break_value)] +#![feature(let_chains)] #![feature(let_else)] -#![feature(never_type)] -#![feature(control_flow_enum)] #![feature(min_specialization)] -#![feature(label_break_value)] +#![feature(never_type)] #![recursion_limit = "512"] // For rustdoc -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 5e93c002168c6..c8ef08f48b609 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -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(); diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 019b64c395eda..13e3dacc30d63 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -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 \ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 4603b5aae20b0..10fec8e115245 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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)] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index f874cf0b42d74..f9c883dd6bf08 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -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. + /// + /// However, consuming ownership is not strictly required. Use a + /// [`From::from`] implementation for an API which strictly + /// consumes ownership. /// - /// 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. + /// # 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::into`] implementation for an API which strictly + /// transfers ownership. /// /// # Example /// diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 842a15ae1bfc0..d378d591ba3a9 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -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)) } } diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index c7f122048a198..48c5fd358d9db 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -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. + /// + /// However, consuming ownership is not strictly required. Use a + /// `From::from` implementation for an API which strictly + /// consumes ownership. + /// + /// # Safety /// - /// 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. + /// 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::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 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 will **consume ownership** of the socket provided and - /// it will be closed when the returned object goes out of scope. + /// However, consuming ownership is not strictly required. Use a + /// `From::from` implementation for an API which strictly + /// consumes ownership. /// - /// 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. + /// # 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::into` implementation for an API which strictly + /// transfers ownership. #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index a695a4106e810..a6b979cc22bd3 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -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); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index dad045887031e..63a8e85f7c540 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -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 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 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(); - } + 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 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), + ); + + 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); diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs new file mode 100644 index 0000000000000..12e576100710a --- /dev/null +++ b/src/test/rustdoc/strip-enum-variant.rs @@ -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, +} diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index f6d467941e3ef..abfb46035376a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -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), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs index 35b1e644a8a71..d7bf91eb69214 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -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), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs index a735379010026..8d4dde42bbeca 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs @@ -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), ]) diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 22a8c53a5852e..1da3b76590481 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -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" }