diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 9b7db9e4c8e65..e42db342f14ee 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { Some(ret_coercion) => { let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); + let ret_ty = self.infcx.shallow_resolve(ret_ty); self.can_coerce(arm_ty, ret_ty) && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) // The match arms need to unify for the case of `impl Trait`. diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 40555bf14eb24..36af539401565 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_vars, ); - let c_result = self.inh.infcx.canonicalize_response(result); + let c_result = self.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); // Normalize only after registering in `user_provided_sigs`. diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 140618e97cca1..fe1e4e74973f0 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -347,7 +347,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .any(|n| roots_reachable_from_non_diverging.visited(n)); let infer_var_infos: UnordBag<_> = self - .inh .infer_var_info .borrow() .items() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8e0be7c7163d9..011607bacc6cd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) { let scope_tree = self.tcx.region_scope_tree(def_id); let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) }; - let mut typeck_results = self.inh.typeck_results.borrow_mut(); + let mut typeck_results = self.typeck_results.borrow_mut(); typeck_results.rvalue_scopes = rvalue_scopes; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index efa2862177e16..74f27cfebbd22 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -7,7 +7,7 @@ mod suggestions; use crate::coercion::DynamicCoerceMany; use crate::fallback::DivergingFallbackBehavior; use crate::fn_ctxt::checks::DivergingBlockBehavior; -use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited}; +use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt}; use hir::def_id::CRATE_DEF_ID; use rustc_errors::{DiagCtxt, ErrorGuaranteed}; use rustc_hir as hir; @@ -108,7 +108,7 @@ pub struct FnCtxt<'a, 'tcx> { pub(super) enclosing_breakables: RefCell>, - pub(super) inh: &'a Inherited<'tcx>, + pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>, pub(super) fallback_has_occurred: Cell, @@ -118,12 +118,12 @@ pub struct FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn new( - inh: &'a Inherited<'tcx>, + root_ctxt: &'a TypeckRootCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, ) -> FnCtxt<'a, 'tcx> { let (diverging_fallback_behavior, diverging_block_behavior) = - parse_never_type_options_attr(inh.tcx); + parse_never_type_options_attr(root_ctxt.tcx); FnCtxt { body_id, param_env, @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { stack: Vec::new(), by_id: Default::default(), }), - inh, + root_ctxt, fallback_has_occurred: Cell::new(false), diverging_fallback_behavior, diverging_block_behavior, @@ -206,9 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { - type Target = Inherited<'tcx>; + type Target = TypeckRootCtxt<'tcx>; fn deref(&self) -> &Self::Target { - self.inh + self.root_ctxt } } diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 1fa799dcec7f1..be5cd6e9d4872 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -95,8 +95,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.lower_ty(ty); - let c_ty = - self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); + let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 0b67b37df29d8..3a16884d5c76a 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -31,7 +31,6 @@ pub mod expr_use_visitor; mod fallback; mod fn_ctxt; mod gather_locals; -mod inherited; mod intrinsicck; mod mem_categorization; mod method; @@ -39,11 +38,12 @@ mod op; mod pat; mod place_op; mod rvalue_scopes; +mod typeck_root_ctxt; mod upvar; mod writeback; pub use fn_ctxt::FnCtxt; -pub use inherited::Inherited; +pub use typeck_root_ctxt::TypeckRootCtxt; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; @@ -170,11 +170,11 @@ fn typeck_with_fallback<'tcx>( let param_env = tcx.param_env(def_id); - let inh = Inherited::new(tcx, def_id); + let root_ctxt = TypeckRootCtxt::new(tcx, def_id); if let Some(inspector) = inspector { - inh.infcx.attach_obligation_inspector(inspector); + root_ctxt.infcx.attach_obligation_inspector(inspector); } - let mut fcx = FnCtxt::new(&inh, param_env, def_id); + let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if decl.output.get_infer_ret_ty().is_some() { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 4dc60f7c6da12..66290b52bf52b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -388,8 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !pat_adjustments.is_empty() { debug!("default binding mode is now {:?}", def_bm); - self.inh - .typeck_results + self.typeck_results .borrow_mut() .pat_adjustments_mut() .insert(pat.hir_id, pat_adjustments); @@ -614,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => BindingMode::convert(ba), }; // ...and store it in a side table: - self.inh.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm); + self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm); debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs similarity index 94% rename from compiler/rustc_hir_typeck/src/inherited.rs rename to compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index b0950ed280084..e493e6a0a7ed9 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -16,7 +16,8 @@ use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, Trai use std::cell::RefCell; use std::ops::Deref; -/// Closures defined within the function. For example: +// Data shared between a "typeck root" and its nested bodies, +/// e.g. closures defined within the function. For example: /// ```ignore (illustrative) /// fn foo() { /// bar(move|| { ... }) @@ -24,8 +25,9 @@ use std::ops::Deref; /// ``` /// Here, the function `foo()` and the closure passed to /// `bar()` will each have their own `FnCtxt`, but they will -/// share the inherited fields. -pub struct Inherited<'tcx> { +/// share the inference context, will process obligations together, +/// can access each other's local types (scoping permitted), etc. +pub struct TypeckRootCtxt<'tcx> { pub(super) infcx: InferCtxt<'tcx>, pub(super) typeck_results: RefCell>, @@ -65,14 +67,14 @@ pub struct Inherited<'tcx> { pub(super) infer_var_info: RefCell>, } -impl<'tcx> Deref for Inherited<'tcx> { +impl<'tcx> Deref for TypeckRootCtxt<'tcx> { type Target = InferCtxt<'tcx>; fn deref(&self) -> &Self::Target { &self.infcx } } -impl<'tcx> Inherited<'tcx> { +impl<'tcx> TypeckRootCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; @@ -83,7 +85,7 @@ impl<'tcx> Inherited<'tcx> { .build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); - Inherited { + TypeckRootCtxt { typeck_results, fulfillment_cx: RefCell::new(>::new(&infcx)), infcx, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 8a27e9a6453b2..3b78e6a43ab33 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -315,30 +315,39 @@ fn test_search_paths_tracking_hash_different_order() { json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), }; + let push = |opts: &mut Options, search_path| { + opts.search_paths.push(SearchPath::from_cli_opt( + "not-a-sysroot".as_ref(), + &opts.target_triple, + &early_dcx, + search_path, + )); + }; + // Reference - v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); - v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); - v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); - v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); - v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); - - v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); - v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); - v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); - v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); - v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); - - v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); - v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); - v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); - v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); - v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); - - v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); - v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); - v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); - v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); - v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); + push(&mut v1, "native=abc"); + push(&mut v1, "crate=def"); + push(&mut v1, "dependency=ghi"); + push(&mut v1, "framework=jkl"); + push(&mut v1, "all=mno"); + + push(&mut v2, "native=abc"); + push(&mut v2, "dependency=ghi"); + push(&mut v2, "crate=def"); + push(&mut v2, "framework=jkl"); + push(&mut v2, "all=mno"); + + push(&mut v3, "crate=def"); + push(&mut v3, "framework=jkl"); + push(&mut v3, "native=abc"); + push(&mut v3, "dependency=ghi"); + push(&mut v3, "all=mno"); + + push(&mut v4, "all=mno"); + push(&mut v4, "native=abc"); + push(&mut v4, "crate=def"); + push(&mut v4, "dependency=ghi"); + push(&mut v4, "framework=jkl"); assert_same_hash(&v1, &v2); assert_same_hash(&v1, &v3); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index fcfd05ccbacf0..6d083e66a9b25 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1111,7 +1111,10 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> { #[derive(Debug, Clone)] pub(crate) struct MatchPair<'pat, 'tcx> { /// This place... - place: PlaceBuilder<'tcx>, + // This can be `None` if it referred to a non-captured place in a closure. + // Invariant: place.is_none() => test_case is Irrefutable + // In other words this must be `Some(_)` after simplification. + place: Option>, /// ... must pass this test... // Invariant: after creation and simplification in `Candidate::new()`, this must not be @@ -1595,11 +1598,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn pick_test( &mut self, candidates: &mut [&mut Candidate<'_, 'tcx>], - ) -> (PlaceBuilder<'tcx>, Test<'tcx>) { + ) -> (Place<'tcx>, Test<'tcx>) { // Extract the match-pair from the highest priority candidate let match_pair = &candidates.first().unwrap().match_pairs[0]; let test = self.test(match_pair); - let match_place = match_pair.place.clone(); + // Unwrap is ok after simplification. + let match_place = match_pair.place.unwrap(); debug!(?test, ?match_pair); (match_place, test) @@ -1640,7 +1644,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`. fn sort_candidates<'b, 'c, 'pat>( &mut self, - match_place: &PlaceBuilder<'tcx>, + match_place: Place<'tcx>, test: &Test<'tcx>, mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], ) -> ( @@ -1658,7 +1662,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // sorting. while let Some(candidate) = candidates.first_mut() { let Some(branch) = - self.sort_candidate(&match_place, test, candidate, &target_candidates) + self.sort_candidate(match_place, test, candidate, &target_candidates) else { break; }; @@ -1786,7 +1790,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // For each of the N possible test outcomes, build the vector of candidates that applies if // the test has that particular outcome. let (remaining_candidates, target_candidates) = - self.sort_candidates(&match_place, &test, candidates); + self.sort_candidates(match_place, &test, candidates); // The block that we should branch to if none of the // `target_candidates` match. @@ -1826,7 +1830,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scrutinee_span, start_block, remainder_start, - &match_place, + match_place, &test, target_blocks, ); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 9d77bd063e114..b66dd83b7ecbb 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -5,7 +5,6 @@ // identify what tests are needed, perform the tests, and then filter // the candidates based on the result. -use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind}; use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; @@ -55,18 +54,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Test { span: match_pair.pattern.span, kind } } - #[instrument(skip(self, target_blocks, place_builder), level = "debug")] + #[instrument(skip(self, target_blocks, place), level = "debug")] pub(super) fn perform_test( &mut self, match_start_span: Span, scrutinee_span: Span, block: BasicBlock, otherwise_block: BasicBlock, - place_builder: &PlaceBuilder<'tcx>, + place: Place<'tcx>, test: &Test<'tcx>, target_blocks: FxIndexMap, BasicBlock>, ) { - let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); debug!(?place, ?place_ty); let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block); @@ -475,7 +473,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// tighter match code if we do something a bit different. pub(super) fn sort_candidate( &mut self, - test_place: &PlaceBuilder<'tcx>, + test_place: Place<'tcx>, test: &Test<'tcx>, candidate: &mut Candidate<'_, 'tcx>, sorted_candidates: &FxIndexMap, Vec<&mut Candidate<'_, 'tcx>>>, @@ -486,8 +484,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // than one, but it'd be very unusual to have two sides that // both require tests; you'd expect one side to be simplified // away.) - let (match_pair_index, match_pair) = - candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?; + let (match_pair_index, match_pair) = candidate + .match_pairs + .iter() + .enumerate() + .find(|&(_, mp)| mp.place == Some(test_place))?; let fully_matched; let ret = match (&test.kind, &match_pair.test_case) { @@ -521,7 +522,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate .match_pairs .iter() - .any(|mp| mp.place == *test_place && is_covering_range(&mp.test_case)) + .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case)) }; if sorted_candidates .get(&TestBranch::Failure) diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 1148cd19a01c7..bc6f0a26582c8 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -95,35 +95,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { pub(in crate::build) fn new( - mut place: PlaceBuilder<'tcx>, + mut place_builder: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, cx: &mut Builder<'_, 'tcx>, ) -> MatchPair<'pat, 'tcx> { // Force the place type to the pattern's type. // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks? - if let Some(resolved) = place.resolve_upvar(cx) { - place = resolved; + if let Some(resolved) = place_builder.resolve_upvar(cx) { + place_builder = resolved; } // Only add the OpaqueCast projection if the given place is an opaque type and the // expected type from the pattern is not. - let may_need_cast = match place.base() { + let may_need_cast = match place_builder.base() { PlaceBase::Local(local) => { - let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty; + let ty = + Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty; ty != pattern.ty && ty.has_opaque_types() } _ => true, }; if may_need_cast { - place = place.project(ProjectionElem::OpaqueCast(pattern.ty)); + place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty)); } + let place = place_builder.try_to_place(cx); let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None }; let mut subpairs = Vec::new(); let test_case = match pattern.kind { PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(), PatKind::Or { ref pats } => TestCase::Or { - pats: pats.iter().map(|pat| FlatPat::new(place.clone(), pat, cx)).collect(), + pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), }, PatKind::Range(ref range) => { @@ -142,13 +144,13 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { .. } => { // Apply the type ascription to the value at `match_pair.place` - let ascription = place.try_to_place(cx).map(|source| super::Ascription { + let ascription = place.map(|source| super::Ascription { annotation: annotation.clone(), source, variance, }); - subpairs.push(MatchPair::new(place.clone(), subpattern, cx)); + subpairs.push(MatchPair::new(place_builder, subpattern, cx)); TestCase::Irrefutable { ascription, binding: None } } @@ -161,7 +163,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { ref subpattern, is_primary: _, } => { - let binding = place.try_to_place(cx).map(|source| super::Binding { + let binding = place.map(|source| super::Binding { span: pattern.span, source, var_id: var, @@ -170,14 +172,14 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now - subpairs.push(MatchPair::new(place.clone(), subpattern, cx)); + subpairs.push(MatchPair::new(place_builder, subpattern, cx)); } TestCase::Irrefutable { ascription: None, binding } } PatKind::InlineConstant { subpattern: ref pattern, def, .. } => { // Apply a type ascription for the inline constant to the value at `match_pair.place` - let ascription = place.try_to_place(cx).map(|source| { + let ascription = place.map(|source| { let span = pattern.span; let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); let args = ty::InlineConstArgs::new( @@ -203,16 +205,16 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { super::Ascription { annotation, source, variance: ty::Contravariant } }); - subpairs.push(MatchPair::new(place.clone(), pattern, cx)); + subpairs.push(MatchPair::new(place_builder, pattern, cx)); TestCase::Irrefutable { ascription, binding: None } } PatKind::Array { ref prefix, ref slice, ref suffix } => { - cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix); + cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix); default_irrefutable() } PatKind::Slice { ref prefix, ref slice, ref suffix } => { - cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix); + cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix); if prefix.is_empty() && slice.is_some() && suffix.is_empty() { default_irrefutable() @@ -225,7 +227,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { } PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => { - let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)` + let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)` subpairs = cx.field_match_pairs(downcast_place, subpatterns); let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { @@ -247,13 +249,12 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { } PatKind::Leaf { ref subpatterns } => { - subpairs = cx.field_match_pairs(place.clone(), subpatterns); + subpairs = cx.field_match_pairs(place_builder, subpatterns); default_irrefutable() } PatKind::Deref { ref subpattern } => { - let place_builder = place.clone().deref(); - subpairs.push(MatchPair::new(place_builder, subpattern, cx)); + subpairs.push(MatchPair::new(place_builder.deref(), subpattern, cx)); default_irrefutable() } @@ -310,8 +311,8 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } else { // Insert a Shallow borrow of any place that is switched on. - if let Some(resolved_place) = match_pair.place.try_to_place(self.cx) { - self.fake_borrows.insert(resolved_place); + if let Some(place) = match_pair.place { + self.fake_borrows.insert(place); } for subpair in &match_pair.subpairs { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 94a95428ab03e..b60ee7649b24a 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1015,8 +1015,8 @@ fn build_construct_coroutine_by_move_shim<'tcx>( bug!(); }; - // We use `*mut Self` here because we only need to emit an ABI-compatible shim body, - // rather than match the signature exactly. + // We use `&mut Self` here because we only need to emit an ABI-compatible shim body, + // rather than match the signature exactly (which might take `&self` instead). // // The self type here is a coroutine-closure, not a coroutine, and we never read from // it because it never has any captures, because this is only true in the Fn/FnMut @@ -1025,7 +1025,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( if receiver_by_ref { // Triple-check that there's no captures here. assert_eq!(args.as_coroutine_closure().tupled_upvars_ty(), tcx.types.unit); - self_ty = Ty::new_mut_ptr(tcx, self_ty); + self_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, self_ty); } let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c06fe29c5673f..f612e8b5b1a55 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2795,11 +2795,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let debuginfo = select_debuginfo(matches, &cg); let debuginfo_compression = unstable_opts.debuginfo_compression; - let mut search_paths = vec![]; - for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(early_dcx, s)); - } - let libs = parse_libs(early_dcx, matches); let test = matches.opt_present("test"); @@ -2848,6 +2843,11 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M candidate.join("library/std/src/lib.rs").is_file().then_some(candidate) }; + let mut search_paths = vec![]; + for s in &matches.opt_strs("L") { + search_paths.push(SearchPath::from_cli_opt(&sysroot, &target_triple, early_dcx, s)); + } + let working_dir = std::env::current_dir().unwrap_or_else(|e| { early_dcx.early_fatal(format!("Current directory is invalid: {e}")); }); diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index 32d5e430717bd..16dd40acef047 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -1,5 +1,6 @@ use crate::filesearch::make_target_lib_path; use crate::EarlyDiagCtxt; +use rustc_target::spec::TargetTriple; use std::path::{Path, PathBuf}; #[derive(Clone, Debug)] @@ -46,7 +47,12 @@ impl PathKind { } impl SearchPath { - pub fn from_cli_opt(early_dcx: &EarlyDiagCtxt, path: &str) -> Self { + pub fn from_cli_opt( + sysroot: &Path, + triple: &TargetTriple, + early_dcx: &EarlyDiagCtxt, + path: &str, + ) -> Self { let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") { (PathKind::Native, stripped) } else if let Some(stripped) = path.strip_prefix("crate=") { @@ -60,12 +66,17 @@ impl SearchPath { } else { (PathKind::All, path) }; - if path.is_empty() { + let dir = match path.strip_prefix("@RUSTC_BUILTIN") { + Some(stripped) => { + make_target_lib_path(sysroot, triple.triple()).join("builtin").join(stripped) + } + None => PathBuf::from(path), + }; + if dir.as_os_str().is_empty() { #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable early_dcx.early_fatal("empty search path given via `-L`"); } - let dir = PathBuf::from(path); Self::new(kind, dir) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index af1dfb6f7e92f..65c3cf1a60748 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -125,8 +125,12 @@ fn fn_sig_for_fn_abi<'tcx>( coroutine_kind = ty::ClosureKind::FnOnce; // Implementations of `FnMut` and `Fn` for coroutine-closures - // still take their receiver by ref. - if receiver_by_ref { Ty::new_mut_ptr(tcx, coroutine_ty) } else { coroutine_ty } + // still take their receiver by (mut) ref. + if receiver_by_ref { + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty) + } else { + coroutine_ty + } } else { tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region) }; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a78842c8f8d68..574a357b44abb 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1726,20 +1726,28 @@ pub(crate) mod builtin { builtin # deref($pat) } - /// Unstable implementation detail of the `rustc` compiler, do not use. + /// Derive macro for `rustc-serialize`. Should not be used in new code. #[rustc_builtin_macro] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, libstd_sys_internals, rt)] + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. pub macro RustcDecodable($item:item) { /* compiler built-in */ } - /// Unstable implementation detail of the `rustc` compiler, do not use. + /// Derive macro for `rustc-serialize`. Should not be used in new code. #[rustc_builtin_macro] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, rt)] + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. pub macro RustcEncodable($item:item) { diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/common.rs similarity index 91% rename from library/core/src/prelude/v1.rs rename to library/core/src/prelude/common.rs index 29f73bb4942aa..b98f3a4659b10 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/common.rs @@ -1,9 +1,7 @@ -//! The first version of the core prelude. +//! Items common to the prelude of all editions. //! //! See the [module-level documentation](super) for more. -#![stable(feature = "core_prelude", since = "1.4.0")] - // Re-exported core operators #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] @@ -68,11 +66,6 @@ pub use crate::{ #[doc(no_inline)] pub use crate::concat_bytes; -// Do not `doc(inline)` these `doc(hidden)` items. -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated)] -pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; - // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index b4791c2c022ec..ca33ef160e88b 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -6,7 +6,26 @@ #![stable(feature = "core_prelude", since = "1.4.0")] -pub mod v1; +mod common; + +/// The first version of the prelude of The Rust Standard Library. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod v1 { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; + + // Do not `doc(inline)` these `doc(hidden)` items. + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] + #[allow(deprecated)] + pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; +} /// The 2015 version of the core prelude. /// @@ -46,14 +65,21 @@ pub mod rust_2021 { pub use crate::convert::{TryFrom, TryInto}; } -/// The 2024 edition of the core prelude. +/// The 2024 version of the core prelude. /// /// See the [module-level documentation](self) for more. #[unstable(feature = "prelude_2024", issue = "121042")] pub mod rust_2024 { - #[unstable(feature = "prelude_2024", issue = "121042")] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; + + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use crate::iter::FromIterator; + + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] - pub use super::rust_2021::*; + pub use crate::convert::{TryFrom, TryInto}; #[unstable(feature = "prelude_2024", issue = "121042")] #[doc(no_inline)] diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index d67493aaf4d65..9b01d2326112d 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -580,6 +580,10 @@ impl io::Read for UnixStream { io::Read::read(&mut &*self, buf) } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + io::Read::read_buf(&mut &*self, buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { io::Read::read_vectored(&mut &*self, bufs) } @@ -596,6 +600,10 @@ impl<'a> io::Read for &'a UnixStream { self.0.read(buf) } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.0.read_vectored(bufs) } diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/common.rs similarity index 91% rename from library/std/src/prelude/v1.rs rename to library/std/src/prelude/common.rs index 36fa4e88b5bde..f61e04e02b666 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/common.rs @@ -1,9 +1,7 @@ -//! The first version of the prelude of The Rust Standard Library. +//! Items common to the prelude of all editions. //! //! See the [module-level documentation](super) for more. -#![stable(feature = "rust1", since = "1.0.0")] - // Re-exported core operators #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] @@ -52,11 +50,6 @@ pub use core::prelude::v1::{ #[doc(no_inline)] pub use core::prelude::v1::concat_bytes; -// Do not `doc(inline)` these `doc(hidden)` items. -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated)] -pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; - // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 7d44d2e4b5da9..0bdbab716adb4 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -93,7 +93,26 @@ #![stable(feature = "rust1", since = "1.0.0")] -pub mod v1; +mod common; + +/// The first version of the prelude of The Rust Standard Library. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod v1 { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; + + // Do not `doc(inline)` these `doc(hidden)` items. + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] + #[allow(deprecated)] + pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; +} /// The 2015 version of the prelude of The Rust Standard Library. /// @@ -134,9 +153,8 @@ pub mod rust_2021 { /// See the [module-level documentation](self) for more. #[unstable(feature = "prelude_2024", issue = "121042")] pub mod rust_2024 { - #[unstable(feature = "prelude_2024", issue = "121042")] - #[doc(no_inline)] - pub use super::v1::*; + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; #[unstable(feature = "prelude_2024", issue = "121042")] #[doc(no_inline)] diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index a1c0321876fa8..9d8cc18b8389e 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -167,6 +167,8 @@ impl FileDesc { } #[cfg(any( + target_os = "aix", + target_os = "dragonfly", // DragonFly 1.5 target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -174,6 +176,7 @@ impl FileDesc { target_os = "illumos", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", // OpenBSD 2.7 ))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { let ret = cvt(unsafe { @@ -188,7 +191,9 @@ impl FileDesc { } #[cfg(not(any( + target_os = "aix", target_os = "android", + target_os = "dragonfly", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -199,6 +204,8 @@ impl FileDesc { target_os = "linux", target_os = "macos", target_os = "netbsd", + target_os = "openbsd", + target_os = "watchos", )))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { io::default_read_vectored(|b| self.read_at(b, offset), bufs) @@ -236,9 +243,10 @@ impl FileDesc { // no `syscall` possible in these platform. #[cfg(any( all(target_os = "android", target_pointer_width = "32"), - target_os = "ios", - target_os = "tvos", - target_os = "macos", + target_os = "ios", // ios 14.0 + target_os = "tvos", // tvos 14.0 + target_os = "macos", // macos 11.0 + target_os = "watchos", // watchos 7.0 ))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); @@ -318,6 +326,8 @@ impl FileDesc { } #[cfg(any( + target_os = "aix", + target_os = "dragonfly", // DragonFly 1.5 target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -325,6 +335,7 @@ impl FileDesc { target_os = "illumos", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", // OpenBSD 2.7 ))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { let ret = cvt(unsafe { @@ -339,7 +350,9 @@ impl FileDesc { } #[cfg(not(any( + target_os = "aix", target_os = "android", + target_os = "dragonfly", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -350,6 +363,8 @@ impl FileDesc { target_os = "linux", target_os = "macos", target_os = "netbsd", + target_os = "openbsd", + target_os = "watchos", )))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { io::default_write_vectored(|b| self.write_at(b, offset), bufs) @@ -387,9 +402,10 @@ impl FileDesc { // no `syscall` possible in these platform. #[cfg(any( all(target_os = "android", target_pointer_width = "32"), - target_os = "ios", - target_os = "tvos", - target_os = "macos", + target_os = "ios", // ios 14.0 + target_os = "tvos", // tvos 14.0 + target_os = "macos", // macos 11.0 + target_os = "watchos", // watchos 7.0 ))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index b968f8df34c23..99b6da60c146d 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -517,7 +517,7 @@ impl FileAttr { #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn modified(&self) -> io::Result { - Ok(SystemTime::from(self.stat.st_mtim)) + SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64) } #[cfg(not(any( @@ -545,7 +545,7 @@ impl FileAttr { #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn accessed(&self) -> io::Result { - Ok(SystemTime::from(self.stat.st_atim)) + SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } #[cfg(any( diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index a3e1b6782e8a8..4cd7c0e3059b1 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -424,7 +424,7 @@ pub fn available_parallelism() -> io::Result> { if !set.is_null() { let mut count: usize = 0; if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 { - for i in 0..u64::MAX { + for i in 0..libc::cpuid_t::MAX { match libc::_cpuset_isset(i, set) { -1 => break, 0 => continue, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f22a9ca604ee2..026c69079999f 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -680,9 +680,13 @@ impl Step for Miri { .arg("--manifest-path") .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml")); cargo.arg("--target").arg(target.rustc_target_arg()); - cargo.arg("--tests"); // don't run doctests, they are too confused by the staging cargo.arg("--").args(builder.config.test_args()); + // `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test". + // Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage. + // So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER). + cargo.env("RUSTDOC", builder.rustdoc(compiler_std)); + // Tell `cargo miri` where to find things. cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); diff --git a/src/doc/unstable-book/src/language-features/adt-const-params.md b/src/doc/unstable-book/src/language-features/adt-const-params.md new file mode 100644 index 0000000000000..208bf5e4c1533 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/adt-const-params.md @@ -0,0 +1,35 @@ +# `adt_const_params` + +The tracking issue for this feature is: [#95174] + +[#95174]: https://github.com/rust-lang/rust/issues/95174 + +------------------------ + +Allows for using more complex types for const parameters, such as structs or enums. + +```rust +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum Foo { + A, + B, + C, +} + +#[derive(ConstParamTy, PartialEq, Eq)] +struct Bar { + flag: bool, +} + +fn is_foo_a_and_bar_true() -> bool { + match (F, B.flag) { + (Foo::A, true) => true, + _ => false, + } +} +``` diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index be7e319bc79f4..f078ad2fb5376 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -460,8 +460,6 @@ impl Options { &matches.free[0] }); - let libs = - matches.opt_strs("L").iter().map(|s| SearchPath::from_cli_opt(early_dcx, s)).collect(); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, @@ -625,6 +623,20 @@ impl Options { } let target = parse_target_triple(early_dcx, matches); + let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); + + let sysroot = match &maybe_sysroot { + Some(s) => s.clone(), + None => { + rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot") + } + }; + + let libs = matches + .opt_strs("L") + .iter() + .map(|s| SearchPath::from_cli_opt(&sysroot, &target, early_dcx, s)) + .collect(); let show_coverage = matches.opt_present("show-coverage"); @@ -653,7 +665,6 @@ impl Options { let bin_crate = crate_types.contains(&CrateType::Executable); let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); - let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let module_sorting = if matches.opt_present("sort-modules-by-appearance") { ModuleSorting::DeclarationOrder } else { diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index 07fbb1cb5c9f8..981a76d683d2e 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -83,7 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { LitFloatType::Unsuffixed => None, }; let (is_whole, is_inf, mut float_str) = match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, FloatTy::F32 => { let value = sym_str.parse::().unwrap(); @@ -94,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, }; if is_inf { @@ -139,10 +145,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { #[must_use] fn max_digits(fty: FloatTy) -> u32 { match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + // FIXME(f16_f128): replace the magic numbers once `{f16,f128}::DIGITS` are available + FloatTy::F16 => 3, FloatTy::F32 => f32::DIGITS, FloatTy::F64 => f64::DIGITS, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => 33, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index bc5dd10cad0a8..e58d477642795 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -12,7 +12,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; -use rustc_hir_typeck::{FnCtxt, Inherited}; +use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; @@ -438,8 +438,8 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< Node::Item(item) => { if let ItemKind::Fn(_, _, body_id) = &item.kind && let output_ty = return_ty(cx, item.owner_id) - && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id) - && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id) + && let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id) + && let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id) && fn_ctxt.can_coerce(ty, output_ty) { if has_lifetime(output_ty) && has_lifetime(ty) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 7a7bb9f9c94c3..15f1890aa39ea 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_hir::Expr; -use rustc_hir_typeck::{cast, FnCtxt, Inherited}; +use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt}; use rustc_lint::LateContext; use rustc_middle::ty::cast::CastKind; use rustc_middle::ty::Ty; @@ -34,8 +34,8 @@ pub(super) fn check_cast<'tcx>( let hir_id = e.hir_id; let local_def_id = hir_id.owner.def_id; - let inherited = Inherited::new(cx.tcx, local_def_id); - let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id); + let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id); + let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id); if let Ok(check) = cast::CastCheck::new( &fn_ctxt, diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index b043805291ea5..26e55b897080c 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -505,6 +505,8 @@ binaries, and as such worth documenting: * `MIRI_LOCAL_CRATES` is set by `cargo-miri` to tell the Miri driver which crates should be given special treatment in diagnostics, in addition to the crate currently being compiled. +* `MIRI_ORIG_RUSTDOC` is set and read by different phases of `cargo-miri` to remember the + value of `RUSTDOC` from before it was overwritten. * `MIRI_VERBOSE` when set to any value tells the various `cargo-miri` phases to perform verbose logging. * `MIRI_HOST_SYSROOT` is set by bootstrap to tell `cargo-miri` which sysroot to use for *host* diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index e547599d954a4..8c0f605fd6ec2 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -202,6 +202,9 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases! // Set rustdoc to us as well, so we can run doctests. + if let Some(orig_rustdoc) = env::var_os("RUSTDOC") { + cmd.env("MIRI_ORIG_RUSTDOC", orig_rustdoc); + } cmd.env("RUSTDOC", &cargo_miri_path); cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata)); @@ -581,9 +584,10 @@ pub fn phase_rustdoc(mut args: impl Iterator) { let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); - // phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here; - // just default to a straight-forward invocation for now: - let mut cmd = Command::new("rustdoc"); + // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup + // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. + let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); + let mut cmd = Command::new(rustdoc); let extern_flag = "--extern"; let runtool_flag = "--runtool"; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs new file mode 100644 index 0000000000000..9b2fc2948bf45 --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -0,0 +1,40 @@ +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +async fn call_once(f: impl async FnOnce(DropMe)) { + f(DropMe("world")).await; +} + +#[derive(Debug)] +struct DropMe(&'static str); + +impl Drop for DropMe { + fn drop(&mut self) { + println!("{}", self.0); + } +} + +pub fn main() { + block_on(async { + let b = DropMe("hello"); + let async_closure = async move |a: DropMe| { + println!("{a:?} {b:?}"); + }; + call_once(async_closure).await; + }); +} diff --git a/src/tools/miri/tests/pass/async-closure-drop.stdout b/src/tools/miri/tests/pass/async-closure-drop.stdout new file mode 100644 index 0000000000000..34cfdedc44ace --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-drop.stdout @@ -0,0 +1,3 @@ +DropMe("world") DropMe("hello") +world +hello diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs index 9b2fc2948bf45..2f7ec2b9e6f86 100644 --- a/src/tools/miri/tests/pass/async-closure.rs +++ b/src/tools/miri/tests/pass/async-closure.rs @@ -1,6 +1,7 @@ #![feature(async_closure, noop_waker, async_fn_traits)] use std::future::Future; +use std::ops::{AsyncFnMut, AsyncFnOnce}; use std::pin::pin; use std::task::*; @@ -16,25 +17,36 @@ pub fn block_on(fut: impl Future) -> T { } } -async fn call_once(f: impl async FnOnce(DropMe)) { - f(DropMe("world")).await; +async fn call_mut(f: &mut impl AsyncFnMut(i32)) { + f(0).await; } -#[derive(Debug)] -struct DropMe(&'static str); +async fn call_once(f: impl AsyncFnOnce(i32)) { + f(1).await; +} -impl Drop for DropMe { - fn drop(&mut self) { - println!("{}", self.0); - } +async fn call_normal>(f: &impl Fn(i32) -> F) { + f(0).await; +} + +async fn call_normal_once>(f: impl FnOnce(i32) -> F) { + f(1).await; } pub fn main() { block_on(async { - let b = DropMe("hello"); - let async_closure = async move |a: DropMe| { - println!("{a:?} {b:?}"); + let b = 2i32; + let mut async_closure = async move |a: i32| { + println!("{a} {b}"); }; + call_mut(&mut async_closure).await; call_once(async_closure).await; + + // No-capture closures implement `Fn`. + let async_closure = async move |a: i32| { + println!("{a}"); + }; + call_normal(&async_closure).await; + call_normal_once(async_closure).await; }); } diff --git a/src/tools/miri/tests/pass/async-closure.stdout b/src/tools/miri/tests/pass/async-closure.stdout index 34cfdedc44ace..7baae1aa94f8d 100644 --- a/src/tools/miri/tests/pass/async-closure.stdout +++ b/src/tools/miri/tests/pass/async-closure.stdout @@ -1,3 +1,4 @@ -DropMe("world") DropMe("hello") -world -hello +0 2 +1 2 +0 +1 diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir index f51540bcfff75..cab7bdb7e3cbf 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { +fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10}; bb0: { diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir index f51540bcfff75..cab7bdb7e3cbf 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { +fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10}; bb0: { diff --git a/tests/run-make-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs index af3d75b3bf216..02b235068a1d2 100644 --- a/tests/run-make-fulldeps/pretty-expanded/input.rs +++ b/tests/run-make-fulldeps/pretty-expanded/input.rs @@ -1,12 +1,8 @@ -#[crate_type="lib"] - // #13544 -extern crate rustc_serialize; - -#[derive(RustcEncodable)] pub struct A; -#[derive(RustcEncodable)] pub struct B(isize); -#[derive(RustcEncodable)] pub struct C { x: isize } -#[derive(RustcEncodable)] pub enum D {} -#[derive(RustcEncodable)] pub enum E { y } -#[derive(RustcEncodable)] pub enum F { z(isize) } +#[derive(Debug)] pub struct A; +#[derive(Debug)] pub struct B(isize); +#[derive(Debug)] pub struct C { x: isize } +#[derive(Debug)] pub enum D {} +#[derive(Debug)] pub enum E { y } +#[derive(Debug)] pub enum F { z(isize) } diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs new file mode 100644 index 0000000000000..d45e0bcd3b457 --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes + +#[inline(never)] +pub fn callback(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} + +#[inline(always)] +pub fn callback_inlined(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs new file mode 100644 index 0000000000000..565d8b65de055 --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes + +#![crate_type = "cdylib"] +#![crate_type = "rlib"] + +#![allow(improper_ctypes_definitions)] + +type Pos = (&'static str, u32); + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +#[no_mangle] +pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) { + inner(outer, pos!()); +} diff --git a/tests/ui/debuginfo/backtrace-dylib-dep.rs b/tests/ui/debuginfo/backtrace-dylib-dep.rs new file mode 100644 index 0000000000000..e2414073edef4 --- /dev/null +++ b/tests/ui/debuginfo/backtrace-dylib-dep.rs @@ -0,0 +1,114 @@ +// Check that backtrace info is correctly generated for dynamic libraries and is usable by a +// rust binary. +// Part of porting some backtrace tests to rustc: . +// Original test: +// +// ignore-tidy-linelength +//@ ignore-android FIXME #17520 +//@ ignore-fuchsia Backtraces not symbolized +//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written). +//@ needs-unwind +//@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes +//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs +//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs +//@ run-pass + +#![allow(improper_ctypes)] +#![allow(improper_ctypes_definitions)] + +extern crate dylib_dep_helper; +extern crate auxiliary; + +use std::backtrace::Backtrace; + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +macro_rules! check { + ($($pos:expr),*) => ({ + verify(&[$($pos,)* pos!()]); + }) +} + +fn verify(filelines: &[Pos]) { + let trace = Backtrace::capture(); + eprintln!("-----------------------------------"); + eprintln!("looking for:"); + for (file, line) in filelines.iter().rev() { + eprintln!("\t{file}:{line}"); + } + eprintln!("found:\n{trace:#?}"); + let mut iter = filelines.iter().rev(); + // FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now, + // this depends on the debug format of `Backtrace` which is of course fragile. + let backtrace = format!("{:#?}", trace); + while let Some((file, line)) = iter.next() { + // FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has + // them. + assert!(backtrace.contains(file), "expected backtrace to contain {}", file); + assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line); + } +} + +type Pos = (&'static str, u32); + +extern "C" { + #[link_name = "foo"] + fn foo(p: Pos, cb: fn(Pos, Pos)); +} + +fn main() { + std::env::set_var("RUST_BACKTRACE", "1"); + + unsafe { + foo(pos!(), |a, b| { + check!(a, b) + }) + } + + outer(pos!()); +} + +#[inline(never)] +fn outer(main_pos: Pos) { + inner(main_pos, pos!()); + inner_inlined(main_pos, pos!()); +} + +#[inline(never)] +fn inner(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +#[inline(always)] +fn inner_inlined(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + + #[inline(always)] + fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(main_pos, outer_pos, inner_pos); + } + inner_further_inlined(main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(main_pos, outer_pos, pos!()); +} diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs new file mode 100644 index 0000000000000..13f8fd5fe22a0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs @@ -0,0 +1,16 @@ +#![crate_type = "lib"] + +// This isn't intended to compile, so it's easiest to just ignore this error. +extern crate rustc_serialize; //~ERROR can't find crate for `rustc_serialize` + +#[derive( + RustcEncodable, + //~^ ERROR use of unstable library feature 'rustc_encodable_decodable' + //~^^ WARNING this was previously accepted by the compiler + //~^^^ WARNING use of deprecated macro `RustcEncodable` + RustcDecodable, + //~^ ERROR use of unstable library feature 'rustc_encodable_decodable' + //~^^ WARNING this was previously accepted by the compiler + //~^^^ WARNING use of deprecated macro `RustcDecodable` +)] +struct S; diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr new file mode 100644 index 0000000000000..02b74dacf4dac --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr @@ -0,0 +1,66 @@ +error[E0463]: can't find crate for `rustc_serialize` + --> $DIR/feature-gate-rustc_encodable_decodable.rs:4:1 + | +LL | extern crate rustc_serialize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate + | + = help: maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` + +error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code + --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 + | +LL | RustcEncodable, + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default + +warning: use of deprecated macro `RustcEncodable`: rustc-serialize is deprecated and no longer supported + --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 + | +LL | RustcEncodable, + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code + --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 + | +LL | RustcDecodable, + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + +warning: use of deprecated macro `RustcDecodable`: rustc-serialize is deprecated and no longer supported + --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 + | +LL | RustcDecodable, + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0463`. +Future incompatibility report: Future breakage diagnostic: +error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code + --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 + | +LL | RustcEncodable, + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default + +Future breakage diagnostic: +error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code + --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 + | +LL | RustcDecodable, + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default +