diff options
248 files changed, 4032 insertions, 3044 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d9e249ee44..5410613548c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" + if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -278,6 +278,10 @@ jobs: env: RUST_BACKTRACE: 1 os: ubuntu-20.04-xl + - name: x86_64-gnu-llvm-12-stage1 + env: + RUST_BACKTRACE: 1 + os: ubuntu-20.04-xl - name: x86_64-gnu-nopt os: ubuntu-20.04-xl env: {} @@ -474,7 +478,7 @@ jobs: uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" + if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -584,7 +588,7 @@ jobs: uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" + if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ac2328a5824..116497109f1 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1111,10 +1111,6 @@ pub struct Expr { pub tokens: Option<LazyTokenStream>, } -// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr, 104); - impl Expr { /// Returns `true` if this expression would be valid somewhere that expects a value; /// for example, an `if` condition. @@ -2883,9 +2879,6 @@ pub enum ItemKind { MacroDef(MacroDef), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ItemKind, 112); - impl ItemKind { pub fn article(&self) -> &str { use ItemKind::*; @@ -2957,9 +2950,6 @@ pub enum AssocItemKind { MacCall(MacCall), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(AssocItemKind, 72); - impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { @@ -3009,9 +2999,6 @@ pub enum ForeignItemKind { MacCall(MacCall), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ForeignItemKind, 72); - impl From<ForeignItemKind> for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { @@ -3038,3 +3025,27 @@ impl TryFrom<ItemKind> for ForeignItemKind { } pub type ForeignItem = Item<ForeignItemKind>; + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(AssocItemKind, 72); + rustc_data_structures::static_assert_size!(Attribute, 152); + rustc_data_structures::static_assert_size!(Block, 48); + rustc_data_structures::static_assert_size!(Expr, 104); + rustc_data_structures::static_assert_size!(Fn, 192); + rustc_data_structures::static_assert_size!(ForeignItemKind, 72); + rustc_data_structures::static_assert_size!(GenericBound, 88); + rustc_data_structures::static_assert_size!(Generics, 72); + rustc_data_structures::static_assert_size!(Impl, 200); + rustc_data_structures::static_assert_size!(Item, 200); + rustc_data_structures::static_assert_size!(ItemKind, 112); + rustc_data_structures::static_assert_size!(Lit, 48); + rustc_data_structures::static_assert_size!(Pat, 120); + rustc_data_structures::static_assert_size!(Path, 40); + rustc_data_structures::static_assert_size!(PathSegment, 24); + rustc_data_structures::static_assert_size!(Stmt, 32); + rustc_data_structures::static_assert_size!(Ty, 96); +} diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index b4fff0022e2..c96474ccb42 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -194,7 +194,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme } for token in rustc_lexer::tokenize(&text[pos..]) { - let token_text = &text[pos..pos + token.len]; + let token_text = &text[pos..pos + token.len as usize]; match token.kind { rustc_lexer::TokenKind::Whitespace => { if let Some(mut idx) = token_text.find('\n') { @@ -211,8 +211,10 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme } rustc_lexer::TokenKind::BlockComment { doc_style, .. } => { if doc_style.is_none() { - let code_to_the_right = - !matches!(text[pos + token.len..].chars().next(), Some('\r' | '\n')); + let code_to_the_right = !matches!( + text[pos + token.len as usize..].chars().next(), + Some('\r' | '\n') + ); let style = match (code_to_the_left, code_to_the_right) { (_, true) => CommentStyle::Mixed, (false, false) => CommentStyle::Isolated, @@ -246,7 +248,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme code_to_the_left = true; } } - pos += token.len; + pos += token.len as usize; } comments diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index ddd54f7c208..d5af74d47fd 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -323,7 +323,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) { // Do not visit the duplicate information in TraitItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let TraitItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii; + let TraitItemRef { id, ident: _, kind: _, span: _ } = *ii; self.visit_nested_trait_item(id); } @@ -331,8 +331,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { // Do not visit the duplicate information in ImplItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _, trait_item_def_id: _ } = - *ii; + let ImplItemRef { id, ident: _, kind: _, span: _, trait_item_def_id: _ } = *ii; self.visit_nested_impl_item(id); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7da49143b46..99f81afc1e2 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -755,17 +755,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(i.id); let trait_item_def_id = hir_id.expect_owner(); - let (generics, kind) = match i.kind { + let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); - (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) + (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { let asyncness = sig.header.asyncness; @@ -778,7 +778,7 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, asyncness.opt_return_id(), ); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } AssocItemKind::TyAlias(box TyAlias { ref generics, @@ -789,7 +789,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, where_clauses, false); - self.lower_generics( + let (generics, kind) = self.lower_generics( &generics, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -805,7 +805,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ) }, - ) + ); + (generics, kind, ty.is_some()) } AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), }; @@ -817,28 +818,25 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, kind, span: self.lower_span(i.span), + defaultness: hir::Defaultness::Default { has_value: has_default }, }; self.arena.alloc(item) } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { - let (kind, has_default) = match &i.kind { - AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()), - AssocItemKind::TyAlias(box TyAlias { ty, .. }) => { - (hir::AssocItemKind::Type, ty.is_some()) - } - AssocItemKind::Fn(box Fn { sig, body, .. }) => { - (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, body.is_some()) + let kind = match &i.kind { + AssocItemKind::Const(..) => hir::AssocItemKind::Const, + AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type, + AssocItemKind::Fn(box Fn { sig, .. }) => { + hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } AssocItemKind::MacCall(..) => unimplemented!(), }; let id = hir::TraitItemId { def_id: self.local_def_id(i.id) }; - let defaultness = hir::Defaultness::Default { has_value: has_default }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - defaultness, kind, } } @@ -849,6 +847,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + // Since `default impl` is not yet implemented, this is always true in impls. + let has_value = true; + let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); + let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); @@ -903,19 +905,16 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), + defaultness, }; self.arena.alloc(item) } fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { - // Since `default impl` is not yet implemented, this is always true in impls. - let has_value = true; - let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { id: hir::ImplItemId { def_id: self.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - defaultness, kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 255c31d0b1a..5da260f980f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -6,7 +6,6 @@ use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_infer::infer::TyCtxtInferExt; @@ -21,6 +20,7 @@ use rustc_middle::ty::{ self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty, }; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; +use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{BytePos, Span, Symbol}; @@ -39,7 +39,7 @@ use crate::{ use super::{ explain_borrow::{BorrowExplanation, LaterUseKind}, - IncludingDowncast, RegionName, RegionNameSource, UseSpans, + DescribePlaceOpt, RegionName, RegionNameSource, UseSpans, }; #[derive(Debug)] @@ -137,7 +137,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, desired_action.as_noun(), partially_str, - self.describe_place_with_options(moved_place, IncludingDowncast(true)), + self.describe_place_with_options( + moved_place, + DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, + ), ); let reinit_spans = maybe_reinitialized_locations @@ -274,8 +277,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let opt_name = - self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); + let opt_name = self.describe_place_with_options( + place.as_ref(), + DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, + ); let note_msg = match opt_name { Some(ref name) => format!("`{}`", name), None => "value".to_owned(), @@ -341,12 +346,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let (name, desc) = - match self.describe_place_with_options(moved_place, IncludingDowncast(true)) { - Some(name) => (format!("`{name}`"), format!("`{name}` ")), - None => ("the variable".to_string(), String::new()), - }; - let path = match self.describe_place_with_options(used_place, IncludingDowncast(true)) { + let (name, desc) = match self.describe_place_with_options( + moved_place, + DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, + ) { + Some(name) => (format!("`{name}`"), format!("`{name}` ")), + None => ("the variable".to_string(), String::new()), + }; + let path = match self.describe_place_with_options( + used_place, + DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, + ) { Some(name) => format!("`{name}`"), None => "value".to_string(), }; @@ -2223,7 +2233,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = self.infcx.tcx.type_of(self.mir_def_id()); match ty.kind() { ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( - self.mir_def_id().to_def_id(), + self.mir_def_id(), self.infcx.tcx.fn_sig(self.mir_def_id()), ), _ => None, @@ -2267,8 +2277,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if our `target` was captured by a closure. if let Rvalue::Aggregate( box AggregateKind::Closure(def_id, substs), - operands, - ) = rvalue + ref operands, + ) = *rvalue { for operand in operands { let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { @@ -2292,7 +2302,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // into a place then we should annotate the closure in // case it ends up being assigned into the return place. annotated_closure = - self.annotate_fn_sig(*def_id, substs.as_closure().sig()); + self.annotate_fn_sig(def_id, substs.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ @@ -2414,12 +2424,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// references. fn annotate_fn_sig( &self, - did: DefId, + did: LocalDefId, sig: ty::PolyFnSig<'tcx>, ) -> Option<AnnotatedBorrowFnSignature<'tcx>> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); - let is_closure = self.infcx.tcx.is_closure(did); - let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did.as_local()?); + let is_closure = self.infcx.tcx.is_closure(did.to_def_id()); + let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did); let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; // We need to work out which arguments to highlight. We do this by looking diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 53c07a3d481..098e8de9420 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,10 +4,10 @@ use itertools::Itertools; use rustc_const_eval::util::{call_kind, CallDesugaringKind}; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; -use rustc_hir::def::Namespace; -use rustc_hir::def_id::DefId; +use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::GeneratorKind; use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, @@ -15,7 +15,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; -use rustc_span::{symbol::sym, Span, DUMMY_SP}; +use rustc_span::def_id::LocalDefId; +use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions; @@ -41,9 +42,16 @@ pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder; pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; pub(crate) use region_name::{RegionName, RegionNameSource}; pub(crate) use rustc_const_eval::util::CallKind; -use rustc_middle::mir::tcx::PlaceTy; -pub(super) struct IncludingDowncast(pub(super) bool); +pub(super) struct DescribePlaceOpt { + pub including_downcast: bool, + + /// Enable/Disable tuple fields. + /// For example `x` tuple. if it's `true` `x.0`. Otherwise `x` + pub including_tuple_field: bool, +} + +pub(super) struct IncludingTupleField(pub(super) bool); impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure @@ -164,7 +172,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// End-user visible description of `place` if one can be found. /// If the place is a temporary for instance, `None` will be returned. pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> { - self.describe_place_with_options(place_ref, IncludingDowncast(false)) + self.describe_place_with_options( + place_ref, + DescribePlaceOpt { including_downcast: false, including_tuple_field: true }, + ) } /// End-user visible description of `place` if one can be found. If the place is a temporary @@ -174,7 +185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(super) fn describe_place_with_options( &self, place: PlaceRef<'tcx>, - including_downcast: IncludingDowncast, + opt: DescribePlaceOpt, ) -> Option<String> { let local = place.local; let mut autoderef_index = None; @@ -224,7 +235,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } - ProjectionElem::Downcast(..) if including_downcast.0 => return None, + ProjectionElem::Downcast(..) if opt.including_downcast => return None, ProjectionElem::Downcast(..) => (), ProjectionElem::Field(field, _ty) => { // FIXME(project-rfc_2229#36): print capture precisely here. @@ -238,9 +249,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let field_name = self.describe_field( PlaceRef { local, projection: place.projection.split_at(index).0 }, *field, + IncludingTupleField(opt.including_tuple_field), ); - buf.push('.'); - buf.push_str(&field_name); + if let Some(field_name_str) = field_name { + buf.push('.'); + buf.push_str(&field_name_str); + } } } ProjectionElem::Index(index) => { @@ -261,6 +275,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ok.ok().map(|_| buf) } + fn describe_name(&self, place: PlaceRef<'tcx>) -> Option<Symbol> { + for elem in place.projection.into_iter() { + match elem { + ProjectionElem::Downcast(Some(name), _) => { + return Some(*name); + } + _ => {} + } + } + None + } + /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> { @@ -275,7 +301,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// End-user visible description of the `field`nth field of `base` - fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String { + fn describe_field( + &self, + place: PlaceRef<'tcx>, + field: Field, + including_tuple_field: IncludingTupleField, + ) -> Option<String> { let place_ty = match place { PlaceRef { local, projection: [] } => PlaceTy::from_ty(self.body.local_decls[local].ty), PlaceRef { local, projection: [proj_base @ .., elem] } => match elem { @@ -289,7 +320,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type), }, }; - self.describe_field_from_ty(place_ty.ty, field, place_ty.variant_index) + self.describe_field_from_ty( + place_ty.ty, + field, + place_ty.variant_index, + including_tuple_field, + ) } /// End-user visible description of the `field_index`nth field of `ty` @@ -298,10 +334,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty: Ty<'_>, field: Field, variant_index: Option<VariantIdx>, - ) -> String { + including_tuple_field: IncludingTupleField, + ) -> Option<String> { if ty.is_box() { // If the type is a box, the field is described from the boxed type - self.describe_field_from_ty(ty.boxed_ty(), field, variant_index) + self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field) } else { match *ty.kind() { ty::Adt(def, _) => { @@ -311,30 +348,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { def.non_enum_variant() }; - variant.fields[field.index()].name.to_string() + if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn { + return None; + } + Some(variant.fields[field.index()].name.to_string()) } - ty::Tuple(_) => field.index().to_string(), + ty::Tuple(_) => Some(field.index().to_string()), ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { - self.describe_field_from_ty(ty, field, variant_index) + self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } ty::Array(ty, _) | ty::Slice(ty) => { - self.describe_field_from_ty(ty, field, variant_index) + self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. // // We know the field exists so it's safe to call operator[] and `unwrap` here. + let def_id = def_id.expect_local(); let var_id = self .infcx .tcx - .typeck(def_id.expect_local()) + .typeck(def_id) .closure_min_captures_flattened(def_id) .nth(field.index()) .unwrap() .get_root_variable(); - self.infcx.tcx.hir().name(var_id).to_string() + Some(self.infcx.tcx.hir().name(var_id).to_string()) } _ => { // Might need a revision when the fields in trait RFC is implemented @@ -715,12 +756,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { - match kind { - box AggregateKind::Closure(def_id, _) - | box AggregateKind::Generator(def_id, _, _) => { + match **kind { + AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { debug!("move_spans: def_id={:?} places={:?}", def_id, places); if let Some((args_span, generator_kind, capture_kind_span, path_span)) = - self.closure_span(*def_id, moved_place, places) + self.closure_span(def_id, moved_place, places) { return ClosureUse { generator_kind, @@ -847,7 +887,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { - let (def_id, is_generator) = match kind { + let (&def_id, is_generator) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), box AggregateKind::Generator(def_id, _, _) => (def_id, true), _ => continue, @@ -858,7 +898,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { def_id, is_generator, places ); if let Some((args_span, generator_kind, capture_kind_span, path_span)) = - self.closure_span(*def_id, Place::from(target).as_ref(), places) + self.closure_span(def_id, Place::from(target).as_ref(), places) { return ClosureUse { generator_kind, args_span, capture_kind_span, path_span }; } else { @@ -879,7 +919,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// The second span is the location the use resulting in the captured path of the capture fn closure_span( &self, - def_id: DefId, + def_id: LocalDefId, target_place: PlaceRef<'tcx>, places: &[Operand<'tcx>], ) -> Option<(Span, Option<GeneratorKind>, Span, Span)> { @@ -887,17 +927,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places ); - let local_did = def_id.as_local()?; - let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did); + let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id); let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr { - for (captured_place, place) in self - .infcx - .tcx - .typeck(def_id.expect_local()) - .closure_min_captures_flattened(def_id) - .zip(places) + for (captured_place, place) in + self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places) { match place { Operand::Copy(place) | Operand::Move(place) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index becb81b2e26..cb3cd479ae2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -6,7 +6,7 @@ use rustc_mir_dataflow::move_paths::{ }; use rustc_span::Span; -use crate::diagnostics::UseSpans; +use crate::diagnostics::{DescribePlaceOpt, UseSpans}; use crate::prefixes::PrefixSet; use crate::MirBorrowckCtxt; @@ -368,13 +368,31 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } _ => { let source = self.borrowed_content_source(deref_base); - match (self.describe_place(move_place.as_ref()), source.describe_for_named_place()) - { - (Some(place_desc), Some(source_desc)) => self.cannot_move_out_of( + let move_place_ref = move_place.as_ref(); + match ( + self.describe_place_with_options( + move_place_ref, + DescribePlaceOpt { + including_downcast: false, + including_tuple_field: false, + }, + ), + self.describe_name(move_place_ref), + source.describe_for_named_place(), + ) { + (Some(place_desc), Some(name), Some(source_desc)) => self.cannot_move_out_of( + span, + &format!("`{place_desc}` as enum variant `{name}` which is behind a {source_desc}"), + ), + (Some(place_desc), Some(name), None) => self.cannot_move_out_of( + span, + &format!("`{place_desc}` as enum variant `{name}`"), + ), + (Some(place_desc), _, Some(source_desc)) => self.cannot_move_out_of( span, &format!("`{place_desc}` which is behind a {source_desc}"), ), - (_, _) => self.cannot_move_out_of( + (_, _, _) => self.cannot_move_out_of( span, &source.describe_for_unnamed_place(self.infcx.tcx), ), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ac26bc9c7f4..0ad4abbce20 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -343,7 +343,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); let tcx = self.infcx.tcx; if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() { - self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); } } @@ -382,7 +382,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind() && let ty::Closure(id, _) = *ty.kind() { - self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); } } @@ -685,11 +685,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn show_mutating_upvar( &self, tcx: TyCtxt<'_>, - id: hir::def_id::DefId, + closure_local_def_id: hir::def_id::LocalDefId, the_place_err: PlaceRef<'tcx>, err: &mut Diagnostic, ) { - let closure_local_def_id = id.expect_local(); let tables = tcx.typeck(closure_local_def_id); let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id); if let Some((span, closure_kind_origin)) = @@ -699,7 +698,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin); let root_hir_id = upvar_id.var_path.hir_id; // we have an origin for this closure kind starting at this root variable so it's safe to unwrap here - let captured_places = tables.closure_min_captures[&id].get(&root_hir_id).unwrap(); + let captured_places = + tables.closure_min_captures[&closure_local_def_id].get(&root_hir_id).unwrap(); let origin_projection = closure_kind_origin .projections diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 0662d4d882f..f68358ecfe6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -189,7 +189,7 @@ impl Display for RegionName { impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId { - self.body.source.def_id().as_local().unwrap() + self.body.source.def_id().expect_local() } pub(crate) fn mir_hir_id(&self) -> hir::HirId { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3e2d57ae00c..4f2a7bccefb 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -189,7 +189,7 @@ fn do_mir_borrowck<'a, 'tcx>( errors.set_tainted_by_errors(); } let upvars: Vec<_> = tables - .closure_min_captures_flattened(def.did.to_def_id()) + .closure_min_captures_flattened(def.did) .map(|captured_place| { let capture = captured_place.info.capture_kind; let by_ref = match capture { @@ -1295,7 +1295,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match **aggregate_kind { AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { let BorrowCheckResult { used_mut_upvars, .. } = - self.infcx.tcx.mir_borrowck(def_id.expect_local()); + self.infcx.tcx.mir_borrowck(def_id); debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); for field in used_mut_upvars { self.propagate_closure_used_mut_upvar(&operands[field.index()]); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cf2140097e6..f7d35da0259 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1847,14 +1847,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.tcx(); let def_id = uv.def.def_id_for_type_of(); if tcx.def_kind(def_id) == DefKind::InlineConst { - let predicates = self.prove_closure_bounds( - tcx, - def_id.expect_local(), - uv.substs, - location, - ); + let def_id = def_id.expect_local(); + let predicates = + self.prove_closure_bounds(tcx, def_id, uv.substs, location); self.normalize_and_prove_instantiated_predicates( - def_id, + def_id.to_def_id(), predicates, location.to_locations(), ); @@ -2514,9 +2511,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { aggregate_kind, location ); - let (def_id, instantiated_predicates) = match aggregate_kind { + let (def_id, instantiated_predicates) = match *aggregate_kind { AggregateKind::Adt(adt_did, _, substs, _, _) => { - (*adt_did, tcx.predicates_of(*adt_did).instantiate(tcx, substs)) + (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, substs)) } // For closures, we have some **extra requirements** we @@ -2541,7 +2538,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // clauses on the struct. AggregateKind::Closure(def_id, substs) | AggregateKind::Generator(def_id, substs, _) => { - (*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)) + (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location)) } AggregateKind::Array(_) | AggregateKind::Tuple => { diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index c92c1051139..b4c79096170 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use object::read::archive::ArchiveFile; @@ -17,9 +17,34 @@ enum ArchiveEntry { File(PathBuf), } +pub(crate) struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { + Box::new(ArArchiveBuilder { + sess, + use_gnu_style_archive: sess.target.archive_format == "gnu", + // FIXME fix builtin ranlib on macOS + no_builtin_ranlib: sess.target.is_like_osx, + + src_archives: vec![], + entries: vec![], + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[rustc_session::cstore::DllImport], + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); + } +} + pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, use_gnu_style_archive: bool, no_builtin_ranlib: bool, @@ -30,19 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { - ArArchiveBuilder { - sess, - dst: output.to_path_buf(), - use_gnu_style_archive: sess.target.archive_format == "gnu", - // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.is_like_osx, - - src_archives: vec![], - entries: vec![], - } - } - fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), @@ -50,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box<dyn FnMut(&str) -> bool + 'static>, + ) -> std::io::Result<()> { let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); let archive = ArchiveFile::parse(&read_cache).unwrap(); let archive_index = self.src_archives.len(); @@ -74,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self: Box<Self>, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder<File>), Gnu(ar::GnuBuilder<File>), @@ -163,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let mut builder = if self.use_gnu_style_archive { BuilderKind::Gnu( ar::GnuBuilder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -178,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } else { BuilderKind::Bsd( ar::Builder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -209,7 +222,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // Run ranlib to be able to link the archive let status = std::process::Command::new(ranlib) - .arg(self.dst) + .arg(output) .status() .expect("Couldn't run ranlib"); @@ -220,17 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn sess(&self) -> &Session { - self.sess - } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &Path, - ) -> PathBuf { - bug!("creating dll imports is not supported"); - } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 568bb20a3f4..bb0793b1deb 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::<crate::archive::ArArchiveBuilder<'_>>(sess, &codegen_results, outputs) + link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 21f62a6b009..f863abdcc97 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -1,14 +1,13 @@ use std::fs::File; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use rustc_session::cstore::DllImport; struct ArchiveConfig<'a> { sess: &'a Session, - dst: PathBuf, use_native_ar: bool, use_gnu_style_archive: bool, } @@ -22,31 +21,44 @@ enum ArchiveEntry { File(PathBuf), } -pub struct ArArchiveBuilder<'a> { - config: ArchiveConfig<'a>, - src_archives: Vec<(PathBuf, ar::Archive<File>)>, - // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at - // the end of an archive for linkers to not get confused. - entries: Vec<(String, ArchiveEntry)>, -} +pub struct ArArchiveBuilderBuilder; -impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { let config = ArchiveConfig { sess, - dst: output.to_path_buf(), use_native_ar: false, // FIXME test for linux and System V derivatives instead use_gnu_style_archive: sess.target.options.archive_format == "gnu", }; - ArArchiveBuilder { + Box::new(ArArchiveBuilder { config, src_archives: vec![], entries: vec![], - } + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[DllImport], + _tmpdir: &Path, + ) -> PathBuf { + unimplemented!(); } +} +pub struct ArArchiveBuilder<'a> { + config: ArchiveConfig<'a>, + src_archives: Vec<(PathBuf, ar::Archive<File>)>, + // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at + // the end of an archive for linkers to not get confused. + entries: Vec<(String, ArchiveEntry)>, +} + +impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string(), @@ -54,10 +66,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box<dyn FnMut(&str) -> bool + 'static>, + ) -> std::io::Result<()> { let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?); let archive_index = self.src_archives.len(); @@ -77,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self: Box<Self>, output: &Path) -> bool { use std::process::Command; fn add_file_using_ar(archive: &Path, file: &Path) { @@ -97,17 +110,17 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } let mut builder = if self.config.use_native_ar { - BuilderKind::NativeAr(&self.config.dst) + BuilderKind::NativeAr(output) } else if self.config.use_gnu_style_archive { BuilderKind::Gnu(ar::GnuBuilder::new( - File::create(&self.config.dst).unwrap(), + File::create(output).unwrap(), self.entries .iter() .map(|(name, _)| name.as_bytes().to_vec()) .collect(), )) } else { - BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap())) + BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap())) }; let any_members = !self.entries.is_empty(); @@ -164,10 +177,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { std::mem::drop(builder); // Run ranlib to be able to link the archive - let status = std::process::Command::new("ranlib") - .arg(self.config.dst) - .status() - .expect("Couldn't run ranlib"); + let status = + std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); if !status.success() { self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code())); @@ -175,17 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn sess(&self) -> &Session { - self.config.sess - } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[DllImport], - _tmpdir: &Path, - ) -> PathBuf { - unimplemented!(); - } } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index c21e0c5a35b..8a206c0368f 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -133,8 +133,9 @@ impl CodegenBackend for GccCodegenBackend { fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::<crate::archive::ArArchiveBuilder<'_>>( + link_binary( sess, + &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs, ) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index baa858709a0..27039cda253 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -10,7 +10,7 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::cstore::{DllCallingConvention, DllImport}; use rustc_session::Session; @@ -18,7 +18,6 @@ use rustc_session::Session; #[must_use = "must call build() to finish building the archive"] pub struct LlvmArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, additions: Vec<Addition>, } @@ -54,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { } impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { - /// Creates a new static archive, ready for modifying the archive specified - /// by `config`. - fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> { - LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() } - } - - fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive: &Path, + skip: Box<dyn FnMut(&str) -> bool + 'static>, + ) -> io::Result<()> { let archive_ro = match ArchiveRO::open(archive) { Ok(ar) => ar, Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), @@ -88,18 +82,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { /// Combine the provided files, rlibs, and native libraries into a single /// `Archive`. - fn build(mut self) -> bool { - match self.build_with_llvm() { + fn build(mut self: Box<Self>, output: &Path) -> bool { + match self.build_with_llvm(output) { Ok(any_members) => any_members, Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)), } } +} + +pub struct LlvmArchiveBuilderBuilder; - fn sess(&self) -> &Session { - self.sess +impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> { + Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) } fn create_dll_import_lib( + &self, sess: &Session, lib_name: &str, dll_imports: &[DllImport], @@ -241,7 +240,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { } impl<'a> LlvmArchiveBuilder<'a> { - fn build_with_llvm(&mut self) -> io::Result<bool> { + fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> { let kind = &*self.sess.target.archive_format; let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| { self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)) @@ -251,7 +250,7 @@ impl<'a> LlvmArchiveBuilder<'a> { let mut strings = Vec::new(); let mut members = Vec::new(); - let dst = CString::new(self.dst.to_str().unwrap())?; + let dst = CString::new(output.to_str().unwrap())?; unsafe { for addition in &mut additions { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 25ce1cef944..eeb1ed61f28 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -370,12 +370,12 @@ impl CodegenBackend for LlvmCodegenBackend { codegen_results: CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { - use crate::back::archive::LlvmArchiveBuilder; + use crate::back::archive::LlvmArchiveBuilderBuilder; use rustc_codegen_ssa::back::link::link_binary; // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs) + link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 53550b049db..0d2aa483d3d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,4 +1,3 @@ -use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_session::cstore::DllImport; use rustc_session::Session; @@ -40,18 +39,8 @@ pub(super) fn find_library( )); } -pub trait ArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self; - - fn add_file(&mut self, path: &Path); - - fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()> - where - F: FnMut(&str) -> bool + 'static; - - fn build(self) -> bool; - - fn sess(&self) -> &Session; +pub trait ArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>; /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>. /// and returns the path on disk to that import library. @@ -59,29 +48,22 @@ pub trait ArchiveBuilder<'a> { /// `linker_with_args`, which is specialized on `ArchiveBuilder` but /// doesn't take or create an instance of that type. fn create_dll_import_lib( + &self, sess: &Session, lib_name: &str, dll_imports: &[DllImport], tmpdir: &Path, ) -> PathBuf; +} - /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library> - /// and adds it to the current compilation's set of archives. - fn inject_dll_import_lib( +pub trait ArchiveBuilder<'a> { + fn add_file(&mut self, path: &Path); + + fn add_archive( &mut self, - lib_name: &str, - dll_imports: &[DllImport], - tmpdir: &MaybeTempDir, - ) { - let output_path = - Self::create_dll_import_lib(self.sess(), lib_name, dll_imports, tmpdir.as_ref()); + archive: &Path, + skip: Box<dyn FnMut(&str) -> bool + 'static>, + ) -> io::Result<()>; - self.add_archive(&output_path, |_| false).unwrap_or_else(|e| { - self.sess().fatal(&format!( - "failed to add native library {}: {}", - output_path.display(), - e - )); - }); - } + fn build(self: Box<Self>, output: &Path) -> bool; } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c26e8d99bbb..13a7b6be947 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -24,7 +24,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; -use super::archive::{find_library, ArchiveBuilder}; +use super::archive::{find_library, ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{create_rmeta_file, MetadataPosition}; @@ -56,8 +56,9 @@ pub fn ensure_removed(diag_handler: &Handler, path: &Path) { /// Performs the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. -pub fn link_binary<'a, B: ArchiveBuilder<'a>>( +pub fn link_binary<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { @@ -101,21 +102,29 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); - link_rlib::<B>( + info!("preparing rlib to {:?}", out_filename); + link_rlib( sess, + archive_builder_builder, codegen_results, RlibFlavor::Normal, - &out_filename, &path, )? - .build(); + .build(&out_filename); } CrateType::Staticlib => { - link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?; + link_staticlib( + sess, + archive_builder_builder, + codegen_results, + &out_filename, + &path, + )?; } _ => { - link_natively::<B>( + link_natively( sess, + archive_builder_builder, crate_type, &out_filename, codegen_results, @@ -245,18 +254,16 @@ pub fn each_linked_rlib( /// the object file of the crate, but it also contains all of the object files from native /// libraries. This is done by unzipping native libraries and inserting all of the contents into /// this archive. -fn link_rlib<'a, B: ArchiveBuilder<'a>>( +fn link_rlib<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, flavor: RlibFlavor, - out_filename: &Path, tmpdir: &MaybeTempDir, -) -> Result<B, ErrorGuaranteed> { - info!("preparing rlib to {:?}", out_filename); - +) -> Result<Box<dyn ArchiveBuilder<'a> + 'a>, ErrorGuaranteed> { let lib_search_paths = archive_search_paths(sess); - let mut ab = <B as ArchiveBuilder>::new(sess, out_filename); + let mut ab = archive_builder_builder.new_archive_builder(sess); let trailing_metadata = match flavor { RlibFlavor::Normal => { @@ -342,7 +349,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( if let Some(name) = lib.name { let location = find_library(name.as_str(), lib.verbatim.unwrap_or(false), &lib_search_paths, sess); - ab.add_archive(&location, |_| false).unwrap_or_else(|e| { + ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| { sess.fatal(&format!( "failed to add native library {}: {}", location.to_string_lossy(), @@ -355,7 +362,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( for (raw_dylib_name, raw_dylib_imports) in collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { - ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); + let output_path = archive_builder_builder.create_dll_import_lib( + sess, + &raw_dylib_name, + &raw_dylib_imports, + tmpdir.as_ref(), + ); + + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| { + sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e)); + }); } if let Some(trailing_metadata) = trailing_metadata { @@ -446,14 +462,21 @@ fn collate_raw_dylibs( /// /// There's no need to include metadata in a static archive, so ensure to not link in the metadata /// object file (and also don't prepare the archive with a metadata file). -fn link_staticlib<'a, B: ArchiveBuilder<'a>>( +fn link_staticlib<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, out_filename: &Path, tempdir: &MaybeTempDir, ) -> Result<(), ErrorGuaranteed> { - let mut ab = - link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?; + info!("preparing staticlib to {:?}", out_filename); + let mut ab = link_rlib( + sess, + archive_builder_builder, + codegen_results, + RlibFlavor::StaticlibBase, + tempdir, + )?; let mut all_native_libs = vec![]; let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { @@ -487,26 +510,29 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( // might be also an extra name suffix let obj_start = name.as_str().to_owned(); - ab.add_archive(path, move |fname: &str| { - // Ignore metadata files, no matter the name. - if fname == METADATA_FILENAME { - return true; - } + ab.add_archive( + path, + Box::new(move |fname: &str| { + // Ignore metadata files, no matter the name. + if fname == METADATA_FILENAME { + return true; + } - // Don't include Rust objects if LTO is enabled - if lto && looks_like_rust_object_file(fname) { - return true; - } + // Don't include Rust objects if LTO is enabled + if lto && looks_like_rust_object_file(fname) { + return true; + } - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { - return true; - } + // Otherwise if this is *not* a rust object and we're skipping + // objects then skip this file + if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { + return true; + } - // ok, don't skip this - false - }) + // ok, don't skip this + false + }), + ) .unwrap(); all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); @@ -515,7 +541,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( sess.fatal(&e); } - ab.build(); + ab.build(out_filename); if !all_native_libs.is_empty() { if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) { @@ -645,8 +671,9 @@ fn link_dwarf_object<'a>( /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream /// files as well. -fn link_natively<'a, B: ArchiveBuilder<'a>>( +fn link_natively<'a>( sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, crate_type: CrateType, out_filename: &Path, codegen_results: &CodegenResults, @@ -654,10 +681,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( ) -> Result<(), ErrorGuaranteed> { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); - let mut cmd = linker_with_args::<B>( + let mut cmd = linker_with_args( &linker_path, flavor, sess, + archive_builder_builder, crate_type, tmpdir, out_filename, @@ -1844,10 +1872,11 @@ fn add_rpath_args( /// to the linking process as a whole. /// Order-independent options may still override each other in order-dependent fashion, /// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`. -fn linker_with_args<'a, B: ArchiveBuilder<'a>>( +fn linker_with_args<'a>( path: &Path, flavor: LinkerFlavor, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, crate_type: CrateType, tmpdir: &Path, out_filename: &Path, @@ -1948,7 +1977,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( } // Upstream rust libraries and their non-bundled static libraries - add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir); + add_upstream_rust_crates( + cmd, + sess, + archive_builder_builder, + codegen_results, + crate_type, + tmpdir, + ); // Upstream dynamic native libraries linked with `#[link]` attributes at and `-l` // command line options. @@ -1963,7 +1999,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( for (raw_dylib_name, raw_dylib_imports) in collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { - cmd.add_object(&B::create_dll_import_lib( + cmd.add_object(&archive_builder_builder.create_dll_import_lib( sess, &raw_dylib_name, &raw_dylib_imports, @@ -2256,9 +2292,10 @@ fn add_local_native_libraries( /// /// Rust crates are not considered at all when creating an rlib output. All dependencies will be /// linked when producing the final output (instead of the intermediate rlib version). -fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( +fn add_upstream_rust_crates<'a>( cmd: &mut dyn Linker, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, crate_type: CrateType, tmpdir: &Path, @@ -2347,7 +2384,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let src = &codegen_results.crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { - add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); } // compiler-builtins are always placed last to ensure that they're // linked correctly. @@ -2357,7 +2394,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); // Link static native libs with "-bundle" modifier only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically @@ -2431,7 +2468,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic` // is used) if let Some(cnum) = compiler_builtins { - add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, cnum); + add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); } // Converts a library file-stem into a cc -l argument @@ -2457,9 +2494,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // Note, however, that if we're not doing LTO we can just pass the rlib // blindly to the linker (fast) because it's fine if it's not actually // included as we're at the end of the dependency chain. - fn add_static_crate<'a, B: ArchiveBuilder<'a>>( + fn add_static_crate<'a>( cmd: &mut dyn Linker, sess: &'a Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, tmpdir: &Path, cnum: CrateNum, @@ -2499,38 +2537,41 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let is_builtins = sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); - let mut archive = <B as ArchiveBuilder>::new(sess, &dst); - if let Err(e) = archive.add_archive(cratepath, move |f| { - if f == METADATA_FILENAME { - return true; - } + let mut archive = archive_builder_builder.new_archive_builder(sess); + if let Err(e) = archive.add_archive( + cratepath, + Box::new(move |f| { + if f == METADATA_FILENAME { + return true; + } - let canonical = f.replace('-', "_"); + let canonical = f.replace('-', "_"); - let is_rust_object = - canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); + let is_rust_object = + canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); - // If we've been requested to skip all native object files - // (those not generated by the rust compiler) then we can skip - // this file. See above for why we may want to do this. - let skip_because_cfg_say_so = skip_native && !is_rust_object; + // If we've been requested to skip all native object files + // (those not generated by the rust compiler) then we can skip + // this file. See above for why we may want to do this. + let skip_because_cfg_say_so = skip_native && !is_rust_object; - // If we're performing LTO and this is a rust-generated object - // file, then we don't need the object file as it's part of the - // LTO module. Note that `#![no_builtins]` is excluded from LTO, - // though, so we let that object file slide. - let skip_because_lto = - upstream_rust_objects_already_included && is_rust_object && is_builtins; + // If we're performing LTO and this is a rust-generated object + // file, then we don't need the object file as it's part of the + // LTO module. Note that `#![no_builtins]` is excluded from LTO, + // though, so we let that object file slide. + let skip_because_lto = + upstream_rust_objects_already_included && is_rust_object && is_builtins; - if skip_because_cfg_say_so || skip_because_lto { - return true; - } + if skip_because_cfg_say_so || skip_because_lto { + return true; + } - false - }) { + false + }), + ) { sess.fatal(&format!("failed to build archive from rlib: {}", e)); } - if archive.build() { + if archive.build(&dst) { link_upstream(&dst); } }); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a4bbdefbb87..ce51b2e9531 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -656,9 +656,7 @@ impl<'a> Linker for GccLinker<'a> { return; } - if crate_type == CrateType::ProcMacro { - return; - } + // FIXME(#99978) hide #[no_mangle] symbols for proc-macros let is_windows = self.sess.target.is_like_windows; let path = tmpdir.join(if is_windows { "list.def" } else { "list" }); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d1a267f7643..e6b6055759d 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -257,16 +257,18 @@ fn exported_symbols_provider_local<'tcx>( })); } - if tcx.sess.crate_types().contains(&CrateType::Dylib) { + if tcx.sess.crate_types().contains(&CrateType::Dylib) + || tcx.sess.crate_types().contains(&CrateType::ProcMacro) + { let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); symbols.push(( exported_symbol, SymbolExportInfo { - level: SymbolExportLevel::Rust, + level: SymbolExportLevel::C, kind: SymbolExportKind::Data, - used: false, + used: true, }, )); } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index de284bd3bae..94ba62c160c 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -37,9 +37,6 @@ pub enum Immediate<Prov: Provenance = AllocId> { Uninit, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Immediate, 56); - impl<Prov: Provenance> From<ScalarMaybeUninit<Prov>> for Immediate<Prov> { #[inline(always)] fn from(val: ScalarMaybeUninit<Prov>) -> Self { @@ -117,9 +114,6 @@ pub struct ImmTy<'tcx, Prov: Provenance = AllocId> { pub layout: TyAndLayout<'tcx>, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); - impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Helper function for printing a scalar to a FmtPrinter @@ -187,9 +181,6 @@ pub enum Operand<Prov: Provenance = AllocId> { Indirect(MemPlace<Prov>), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Operand, 64); - #[derive(Clone, Debug)] pub struct OpTy<'tcx, Prov: Provenance = AllocId> { op: Operand<Prov>, // Keep this private; it helps enforce invariants. @@ -204,9 +195,6 @@ pub struct OpTy<'tcx, Prov: Provenance = AllocId> { pub align: Option<Align>, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(OpTy<'_>, 88); - impl<'tcx, Prov: Provenance> std::ops::Deref for OpTy<'tcx, Prov> { type Target = Operand<Prov>; #[inline(always)] @@ -830,3 +818,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } } + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(Immediate, 56); + rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); + rustc_data_structures::static_assert_size!(Operand, 64); + rustc_data_structures::static_assert_size!(OpTy<'_>, 88); +} diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 473da71a0ab..f4571a1ca3d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -25,9 +25,6 @@ pub enum MemPlaceMeta<Prov: Provenance = AllocId> { None, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); - impl<Prov: Provenance> MemPlaceMeta<Prov> { pub fn unwrap_meta(self) -> Scalar<Prov> { match self { @@ -56,9 +53,6 @@ pub struct MemPlace<Prov: Provenance = AllocId> { pub meta: MemPlaceMeta<Prov>, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MemPlace, 40); - /// A MemPlace with its layout. Constructing it is only possible in this module. #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct MPlaceTy<'tcx, Prov: Provenance = AllocId> { @@ -71,9 +65,6 @@ pub struct MPlaceTy<'tcx, Prov: Provenance = AllocId> { pub align: Align, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64); - #[derive(Copy, Clone, Debug)] pub enum Place<Prov: Provenance = AllocId> { /// A place referring to a value allocated in the `Memory` system. @@ -84,9 +75,6 @@ pub enum Place<Prov: Provenance = AllocId> { Local { frame: usize, local: mir::Local }, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Place, 48); - #[derive(Clone, Debug)] pub struct PlaceTy<'tcx, Prov: Provenance = AllocId> { place: Place<Prov>, // Keep this private; it helps enforce invariants. @@ -98,9 +86,6 @@ pub struct PlaceTy<'tcx, Prov: Provenance = AllocId> { pub align: Align, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72); - impl<'tcx, Prov: Provenance> std::ops::Deref for PlaceTy<'tcx, Prov> { type Target = Place<Prov>; #[inline(always)] @@ -901,3 +886,15 @@ where Ok(mplace) } } + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); + rustc_data_structures::static_assert_size!(MemPlace, 40); + rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64); + rustc_data_structures::static_assert_size!(Place, 48); + rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72); +} diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d20f16755c3..6f6717721fb 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -238,7 +238,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(local_def_id) = def_id.as_local() { let tables = self.ecx.tcx.typeck(local_def_id); if let Some(captured_place) = - tables.closure_min_captures_flattened(*def_id).nth(field) + tables.closure_min_captures_flattened(local_def_id).nth(field) { // Sometimes the index is beyond the number of upvars (seen // for a generator). diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 628298df473..0adb88a180f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let mut nonconst_call_permission = false; if let Some(callee_trait) = tcx.trait_of_item(callee) && tcx.has_attr(callee_trait, sym::const_trait) - && Some(callee_trait) == tcx.trait_of_item(caller) + && Some(callee_trait) == tcx.trait_of_item(caller.to_def_id()) // Can only call methods when it's `<Self as TheTrait>::f`. && tcx.types.self_param == substs.type_at(0) { diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs index a7a480dd1d7..af9d83f0609 100644 --- a/compiler/rustc_const_eval/src/util/call_kind.rs +++ b/compiler/rustc_const_eval/src/util/call_kind.rs @@ -66,9 +66,12 @@ pub fn call_kind<'tcx>( from_hir_call: bool, self_arg: Option<Ident>, ) -> CallKind<'tcx> { - let parent = tcx.opt_associated_item(method_did).and_then(|assoc| match assoc.container { - AssocItemContainer::ImplContainer(impl_did) => tcx.trait_id_of_impl(impl_did), - AssocItemContainer::TraitContainer(trait_did) => Some(trait_did), + let parent = tcx.opt_associated_item(method_did).and_then(|assoc| { + let container_id = assoc.container_id(tcx); + match assoc.container { + AssocItemContainer::ImplContainer => tcx.trait_id_of_impl(container_id), + AssocItemContainer::TraitContainer => Some(container_id), + } }); let fn_call = parent diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 5f8801cc4e2..c2c551e78a4 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -338,7 +338,12 @@ impl Definitions { /// Adds a definition with a parent definition. pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId { - debug!("create_def(parent={:?}, data={:?})", parent, data); + // We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a + // reference to `Definitions` and we're already holding a mutable reference. + debug!( + "create_def(parent={}, data={data:?})", + self.def_path(parent).to_string_no_crate_verbose(), + ); // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f71400898e6..617433a9803 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2222,6 +2222,7 @@ pub struct TraitItem<'hir> { pub generics: &'hir Generics<'hir>, pub kind: TraitItemKind<'hir>, pub span: Span, + pub defaultness: Defaultness, } impl TraitItem<'_> { @@ -2281,6 +2282,7 @@ pub struct ImplItem<'hir> { pub def_id: LocalDefId, pub generics: &'hir Generics<'hir>, pub kind: ImplItemKind<'hir>, + pub defaultness: Defaultness, pub span: Span, pub vis_span: Span, } @@ -3083,7 +3085,6 @@ pub struct TraitItemRef { pub ident: Ident, pub kind: AssocItemKind, pub span: Span, - pub defaultness: Defaultness, } /// A reference from an impl to one of its associated items. This @@ -3098,7 +3099,6 @@ pub struct ImplItemRef { pub ident: Ident, pub kind: AssocItemKind, pub span: Span, - pub defaultness: Defaultness, /// When we are in a trait impl, link to the trait-item's id. pub trait_item_def_id: Option<DefId>, } @@ -3489,17 +3489,18 @@ impl<'hir> Node<'hir> { // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { - rustc_data_structures::static_assert_size!(super::Block<'static>, 48); - rustc_data_structures::static_assert_size!(super::Expr<'static>, 56); - rustc_data_structures::static_assert_size!(super::Pat<'static>, 88); - rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); - rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); - rustc_data_structures::static_assert_size!(super::GenericBound<'_>, 48); - rustc_data_structures::static_assert_size!(super::Generics<'static>, 56); - rustc_data_structures::static_assert_size!(super::Impl<'static>, 80); - - rustc_data_structures::static_assert_size!(super::Item<'static>, 80); - rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 88); - rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 80); - rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 72); + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(Block<'static>, 48); + rustc_data_structures::static_assert_size!(Expr<'static>, 56); + rustc_data_structures::static_assert_size!(ForeignItem<'static>, 72); + rustc_data_structures::static_assert_size!(GenericBound<'_>, 48); + rustc_data_structures::static_assert_size!(Generics<'static>, 56); + rustc_data_structures::static_assert_size!(ImplItem<'static>, 88); + rustc_data_structures::static_assert_size!(Impl<'static>, 80); + rustc_data_structures::static_assert_size!(Item<'static>, 80); + rustc_data_structures::static_assert_size!(Pat<'static>, 88); + rustc_data_structures::static_assert_size!(QPath<'static>, 24); + rustc_data_structures::static_assert_size!(TraitItem<'static>, 96); + rustc_data_structures::static_assert_size!(Ty<'static>, 72); } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 640974115b9..e676acebe35 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -946,32 +946,30 @@ pub fn walk_fn<'v, V: Visitor<'v>>( } pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { - visitor.visit_ident(trait_item.ident); - visitor.visit_generics(&trait_item.generics); - match trait_item.kind { + // N.B., deliberately force a compilation error if/when new fields are added. + let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item; + let hir_id = trait_item.hir_id(); + visitor.visit_ident(ident); + visitor.visit_generics(&generics); + visitor.visit_defaultness(&defaultness); + match *kind { TraitItemKind::Const(ref ty, default) => { - visitor.visit_id(trait_item.hir_id()); + visitor.visit_id(hir_id); visitor.visit_ty(ty); walk_list!(visitor, visit_nested_body, default); } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { - visitor.visit_id(trait_item.hir_id()); + visitor.visit_id(hir_id); visitor.visit_fn_decl(&sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { - visitor.visit_fn( - FnKind::Method(trait_item.ident, sig), - &sig.decl, - body_id, - trait_item.span, - trait_item.hir_id(), - ); + visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id); } TraitItemKind::Type(bounds, ref default) => { - visitor.visit_id(trait_item.hir_id()); + visitor.visit_id(hir_id); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } @@ -980,19 +978,27 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { // N.B., deliberately force a compilation error if/when new fields are added. - let TraitItemRef { id, ident, ref kind, span: _, ref defaultness } = *trait_item_ref; + let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref; visitor.visit_nested_trait_item(id); visitor.visit_ident(ident); visitor.visit_associated_item_kind(kind); - visitor.visit_defaultness(defaultness); } pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItem { def_id: _, ident, ref generics, ref kind, span: _, vis_span: _ } = *impl_item; + let ImplItem { + def_id: _, + ident, + ref generics, + ref kind, + ref defaultness, + span: _, + vis_span: _, + } = *impl_item; visitor.visit_ident(ident); visitor.visit_generics(generics); + visitor.visit_defaultness(defaultness); match *kind { ImplItemKind::Const(ref ty, body) => { visitor.visit_id(impl_item.hir_id()); @@ -1027,12 +1033,10 @@ pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItemRef { id, ident, ref kind, span: _, ref defaultness, trait_item_def_id: _ } = - *impl_item_ref; + let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref; visitor.visit_nested_impl_item(id); visitor.visit_ident(ident); visitor.visit_associated_item_kind(kind); - visitor.visit_defaultness(defaultness); } pub fn walk_struct_def<'v, V: Visitor<'v>>( diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 35a278e6c92..710c4a01b24 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -80,7 +80,7 @@ const BASE_STRUCT: &[&str] = /// Extra `DepNode`s for functions and methods. const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item]; -const EXTRA_TRAIT: &[&str] = &[label_strs::trait_of_item]; +const EXTRA_TRAIT: &[&str] = &[]; // Fully Built Labels diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 5b664e19c18..777112442f0 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1061,12 +1061,8 @@ impl<T> Clone for BitSet<T> { } fn clone_from(&mut self, from: &Self) { - if self.domain_size != from.domain_size { - self.words.resize(from.domain_size, 0); - self.domain_size = from.domain_size; - } - - self.words.copy_from_slice(&from.words); + self.domain_size = from.domain_size; + self.words.clone_from(&from.words); } } diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index a58133e4aed..351d62feed9 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -41,6 +41,23 @@ fn bitset_iter_works_2() { } #[test] +fn bitset_clone_from() { + let mut a: BitSet<usize> = BitSet::new_empty(10); + a.insert(4); + a.insert(7); + a.insert(9); + + let mut b = BitSet::new_empty(2); + b.clone_from(&a); + assert_eq!(b.domain_size(), 10); + assert_eq!(b.iter().collect::<Vec<_>>(), [4, 7, 9]); + + b.clone_from(&BitSet::new_empty(40)); + assert_eq!(b.domain_size(), 40); + assert_eq!(b.iter().collect::<Vec<_>>(), []); +} + +#[test] fn union_two_sets() { let mut set1: BitSet<usize> = BitSet::new_empty(65); let mut set2: BitSet<usize> = BitSet::new_empty(65); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 39faed0bf36..20864c657ff 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -712,7 +712,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { opt_suggest_box_span, }) => { let then_span = self.find_block_span_from_hir_id(then_id); - let else_span = self.find_block_span_from_hir_id(then_id); + let else_span = self.find_block_span_from_hir_id(else_id); err.span_label(then_span, "expected because of this"); if let Some(sp) = outer_span { err.span_label(sp, "`if` and `else` have incompatible types"); @@ -760,11 +760,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { second_ty: Ty<'tcx>, second_span: Span, ) { - let remove_semicolon = - [(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| { - let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None }; - self.could_remove_semicolon(blk, ty) - }); + let remove_semicolon = [ + (first_id, self.resolve_vars_if_possible(second_ty)), + (second_id, self.resolve_vars_if_possible(first_ty)), + ] + .into_iter() + .find_map(|(id, ty)| { + let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None }; + self.could_remove_semicolon(blk, ty) + }); match remove_semicolon { Some((sp, StatementAsExpression::NeedsBoxing)) => { err.multipart_suggestion( 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 246d27be71c..9886c572a8a 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 @@ -76,10 +76,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { "...is used and required to live as long as `'static` here \ because of an implicit lifetime bound on the {}", match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer(id) => - format!("`impl` of `{}`", tcx.def_path_str(id)), - AssocItemContainer::ImplContainer(_) => - "inherent `impl`".to_string(), + AssocItemContainer::TraitContainer => { + let id = ctxt.assoc_item.container_id(tcx); + format!("`impl` of `{}`", tcx.def_path_str(id)) + } + AssocItemContainer::ImplContainer => "inherent `impl`".to_string(), }, ), ); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6d5f4993d8d..0424b5a7c44 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -8,7 +8,7 @@ pub use self::ValuePairs::*; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; -use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; +use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -645,9 +645,7 @@ impl<'tcx, T> InferOk<'tcx, T> { fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> T { let InferOk { value, obligations } = self; - for obligation in obligations { - fulfill_cx.register_predicate_obligation(infcx, obligation); - } + fulfill_cx.register_predicate_obligations(infcx, obligations); value } } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 4c64e679b95..5e5596f13c8 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -117,7 +117,6 @@ pub fn create_session( let mut check_cfg = config::to_crate_check_config(check_cfg); check_cfg.fill_well_known(); - check_cfg.fill_actual(&cfg); sess.parse_sess.config = cfg; sess.parse_sess.check_config = check_cfg; diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index 0ba6c56dbb5..21557a9c854 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -61,8 +61,8 @@ impl<'a> Cursor<'a> { } /// Returns amount of already consumed symbols. - pub(crate) fn len_consumed(&self) -> usize { - self.initial_len - self.chars.as_str().len() + pub(crate) fn len_consumed(&self) -> u32 { + (self.initial_len - self.chars.as_str().len()) as u32 } /// Resets the number of bytes consumed to 0. diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index a41e0374f41..6d311af9007 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -38,18 +38,17 @@ use std::convert::TryFrom; #[derive(Debug)] pub struct Token { pub kind: TokenKind, - pub len: usize, + pub len: u32, } impl Token { - fn new(kind: TokenKind, len: usize) -> Token { + fn new(kind: TokenKind, len: u32) -> Token { Token { kind, len } } } /// Enum representing common lexeme types. -// perf note: Changing all `usize` to `u32` doesn't change performance. See #77629 -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum TokenKind { // Multi-char tokens: /// "// comment" @@ -76,7 +75,7 @@ pub enum TokenKind { /// tokens. UnknownPrefix, /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details. - Literal { kind: LiteralKind, suffix_start: usize }, + Literal { kind: LiteralKind, suffix_start: u32 }, /// "'a" Lifetime { starts_with_number: bool }, @@ -160,26 +159,24 @@ pub enum LiteralKind { Str { terminated: bool }, /// "b"abc"", "b"abc" ByteStr { terminated: bool }, - /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a" - RawStr { n_hashes: u8, err: Option<RawStrError> }, - /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a" - RawByteStr { n_hashes: u8, err: Option<RawStrError> }, + /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a". `None` indicates + /// an invalid literal. + RawStr { n_hashes: Option<u8> }, + /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a". `None` + /// indicates an invalid literal. + RawByteStr { n_hashes: Option<u8> }, } -/// Error produced validating a raw string. Represents cases like: -/// - `r##~"abcde"##`: `InvalidStarter` -/// - `r###"abcde"##`: `NoTerminator { expected: 3, found: 2, possible_terminator_offset: Some(11)` -/// - Too many `#`s (>255): `TooManyDelimiters` -// perf note: It doesn't matter that this makes `Token` 36 bytes bigger. See #77629 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum RawStrError { - /// Non `#` characters exist between `r` and `"` eg. `r#~"..` + /// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##` InvalidStarter { bad_char: char }, - /// The string was never terminated. `possible_terminator_offset` is the number of characters after `r` or `br` where they - /// may have intended to terminate it. - NoTerminator { expected: usize, found: usize, possible_terminator_offset: Option<usize> }, + /// The string was not terminated, e.g. `r###"abcde"##`. + /// `possible_terminator_offset` is the number of characters after `r` or + /// `br` where they may have intended to terminate it. + NoTerminator { expected: u32, found: u32, possible_terminator_offset: Option<u32> }, /// More than 255 `#`s exist. - TooManyDelimiters { found: usize }, + TooManyDelimiters { found: u32 }, } /// Base of numeric literal encoding according to its prefix. @@ -221,11 +218,25 @@ pub fn strip_shebang(input: &str) -> Option<usize> { } /// Parses the first token from the provided input string. +#[inline] pub fn first_token(input: &str) -> Token { debug_assert!(!input.is_empty()); Cursor::new(input).advance_token() } +/// Validates a raw string literal. Used for getting more information about a +/// problem with a `RawStr`/`RawByteStr` with a `None` field. +#[inline] +pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> { + debug_assert!(!input.is_empty()); + let mut cursor = Cursor::new(input); + // Move past the leading `r` or `br`. + for _ in 0..prefix_len { + cursor.bump().unwrap(); + } + cursor.raw_double_quoted_string(prefix_len).map(|_| ()) +} + /// Creates an iterator that produces tokens from the input string. pub fn tokenize(input: &str) -> impl Iterator<Item = Token> + '_ { let mut cursor = Cursor::new(input); @@ -315,12 +326,12 @@ impl Cursor<'_> { 'r' => match (self.first(), self.second()) { ('#', c1) if is_id_start(c1) => self.raw_ident(), ('#', _) | ('"', _) => { - let (n_hashes, err) = self.raw_double_quoted_string(1); + let res = self.raw_double_quoted_string(1); let suffix_start = self.len_consumed(); - if err.is_none() { + if res.is_ok() { self.eat_literal_suffix(); } - let kind = RawStr { n_hashes, err }; + let kind = RawStr { n_hashes: res.ok() }; Literal { kind, suffix_start } } _ => self.ident_or_unknown_prefix(), @@ -350,12 +361,12 @@ impl Cursor<'_> { } ('r', '"') | ('r', '#') => { self.bump(); - let (n_hashes, err) = self.raw_double_quoted_string(2); + let res = self.raw_double_quoted_string(2); let suffix_start = self.len_consumed(); - if err.is_none() { + if res.is_ok() { self.eat_literal_suffix(); } - let kind = RawByteStr { n_hashes, err }; + let kind = RawByteStr { n_hashes: res.ok() }; Literal { kind, suffix_start } } _ => self.ident_or_unknown_prefix(), @@ -698,19 +709,18 @@ impl Cursor<'_> { } /// Eats the double-quoted string and returns `n_hashes` and an error if encountered. - fn raw_double_quoted_string(&mut self, prefix_len: usize) -> (u8, Option<RawStrError>) { + fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> { // Wrap the actual function to handle the error with too many hashes. // This way, it eats the whole raw string. - let (n_hashes, err) = self.raw_string_unvalidated(prefix_len); + let n_hashes = self.raw_string_unvalidated(prefix_len)?; // Only up to 255 `#`s are allowed in raw strings match u8::try_from(n_hashes) { - Ok(num) => (num, err), - // We lie about the number of hashes here :P - Err(_) => (0, Some(RawStrError::TooManyDelimiters { found: n_hashes })), + Ok(num) => Ok(num), + Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }), } } - fn raw_string_unvalidated(&mut self, prefix_len: usize) -> (usize, Option<RawStrError>) { + fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> { debug_assert!(self.prev() == 'r'); let start_pos = self.len_consumed(); let mut possible_terminator_offset = None; @@ -729,7 +739,7 @@ impl Cursor<'_> { Some('"') => (), c => { let c = c.unwrap_or(EOF_CHAR); - return (n_start_hashes, Some(RawStrError::InvalidStarter { bad_char: c })); + return Err(RawStrError::InvalidStarter { bad_char: c }); } } @@ -739,14 +749,11 @@ impl Cursor<'_> { self.eat_while(|c| c != '"'); if self.is_eof() { - return ( - n_start_hashes, - Some(RawStrError::NoTerminator { - expected: n_start_hashes, - found: max_hashes, - possible_terminator_offset, - }), - ); + return Err(RawStrError::NoTerminator { + expected: n_start_hashes, + found: max_hashes, + possible_terminator_offset, + }); } // Eat closing double quote. @@ -764,7 +771,7 @@ impl Cursor<'_> { } if n_end_hashes == n_start_hashes { - return (n_start_hashes, None); + return Ok(n_start_hashes); } else if n_end_hashes > max_hashes { // Keep track of possible terminators to give a hint about // where there might be a missing terminator diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index 07daee06f0f..e4c1787f2cc 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -2,42 +2,39 @@ use super::*; use expect_test::{expect, Expect}; -fn check_raw_str(s: &str, expected_hashes: u8, expected_err: Option<RawStrError>) { +fn check_raw_str(s: &str, expected: Result<u8, RawStrError>) { let s = &format!("r{}", s); let mut cursor = Cursor::new(s); cursor.bump(); - let (n_hashes, err) = cursor.raw_double_quoted_string(0); - assert_eq!(n_hashes, expected_hashes); - assert_eq!(err, expected_err); + let res = cursor.raw_double_quoted_string(0); + assert_eq!(res, expected); } #[test] fn test_naked_raw_str() { - check_raw_str(r#""abc""#, 0, None); + check_raw_str(r#""abc""#, Ok(0)); } #[test] fn test_raw_no_start() { - check_raw_str(r##""abc"#"##, 0, None); + check_raw_str(r##""abc"#"##, Ok(0)); } #[test] fn test_too_many_terminators() { // this error is handled in the parser later - check_raw_str(r###"#"abc"##"###, 1, None); + check_raw_str(r###"#"abc"##"###, Ok(1)); } #[test] fn test_unterminated() { check_raw_str( r#"#"abc"#, - 1, - Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }), + Err(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }), ); check_raw_str( r###"##"abc"#"###, - 2, - Some(RawStrError::NoTerminator { + Err(RawStrError::NoTerminator { expected: 2, found: 1, possible_terminator_offset: Some(7), @@ -46,14 +43,13 @@ fn test_unterminated() { // We're looking for "# not just any # check_raw_str( r###"##"abc#"###, - 2, - Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }), + Err(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }), ) } #[test] fn test_invalid_start() { - check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' })); + check_raw_str(r##"#~"abc"#"##, Err(RawStrError::InvalidStarter { bad_char: '~' })); } #[test] @@ -61,26 +57,24 @@ fn test_unterminated_no_pound() { // https://github.com/rust-lang/rust/issues/70677 check_raw_str( r#"""#, - 0, - Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }), + Err(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }), ); } #[test] fn test_too_many_hashes() { let max_count = u8::MAX; - let mut hashes: String = "#".repeat(max_count.into()); + let hashes1 = "#".repeat(max_count as usize); + let hashes2 = "#".repeat(max_count as usize + 1); + let middle = "\"abc\""; + let s1 = [&hashes1, middle, &hashes1].join(""); + let s2 = [&hashes2, middle, &hashes2].join(""); - // Valid number of hashes (255 = 2^8 - 1 = u8::MAX), but invalid string. - check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' })); + // Valid number of hashes (255 = 2^8 - 1 = u8::MAX). + check_raw_str(&s1, Ok(255)); // One more hash sign (256 = 2^8) becomes too many. - hashes.push('#'); - check_raw_str( - &hashes, - 0, - Some(RawStrError::TooManyDelimiters { found: usize::from(max_count) + 1 }), - ); + check_raw_str(&s2, Err(RawStrError::TooManyDelimiters { found: u32::from(max_count) + 1 })); } #[test] @@ -251,7 +245,7 @@ fn raw_string() { check_lexing( "r###\"\"#a\\b\x00c\"\"###", expect![[r#" - Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 17 }, len: 17 } + Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 17 }, len: 17 } "#]], ) } @@ -295,9 +289,9 @@ br###"raw"###suffix Token { kind: Whitespace, len: 1 } Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 }, len: 3 } Token { kind: Whitespace, len: 1 } - Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 12 }, len: 18 } + Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 12 }, len: 18 } Token { kind: Whitespace, len: 1 } - Token { kind: Literal { kind: RawByteStr { n_hashes: 3, err: None }, suffix_start: 13 }, len: 19 } + Token { kind: Literal { kind: RawByteStr { n_hashes: Some(3) }, suffix_start: 13 }, len: 19 } Token { kind: Whitespace, len: 1 } "#]], ) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ca3e6ce4d60..bd58021f78f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1364,7 +1364,6 @@ impl UnreachablePub { cx: &LateContext<'_>, what: &str, def_id: LocalDefId, - span: Span, vis_span: Span, exportable: bool, ) { @@ -1373,7 +1372,7 @@ impl UnreachablePub { if vis_span.from_expansion() { applicability = Applicability::MaybeIncorrect; } - let def_span = cx.tcx.sess.source_map().guess_head_span(span); + let def_span = cx.tcx.def_span(def_id); cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { let mut err = lint.build(fluent::lint::builtin_unreachable_pub); err.set_arg("what", what); @@ -1399,36 +1398,22 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id, item.span, item.vis_span, true); + self.perform_lint(cx, "item", item.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint( - cx, - "item", - foreign_item.def_id, - foreign_item.span, - foreign_item.vis_span, - true, - ); + self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { let def_id = cx.tcx.hir().local_def_id(field.hir_id); - self.perform_lint(cx, "field", def_id, field.span, field.vis_span, false); + self.perform_lint(cx, "field", def_id, field.vis_span, false); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Only lint inherent impl items. if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { - self.perform_lint( - cx, - "item", - impl_item.def_id, - impl_item.span, - impl_item.vis_span, - false, - ); + self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false); } } } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 33ac2ed02aa..8d04d68bf1c 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -22,8 +22,8 @@ pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext let def_id = cx.tcx.hir().local_def_id(id); let item = cx.tcx.associated_item(def_id); match item.container { - ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl, - ty::ImplContainer(cid) => match cx.tcx.impl_trait_ref(cid) { + ty::TraitContainer => MethodLateContext::TraitAutoImpl, + ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { Some(_) => MethodLateContext::TraitImpl, None => MethodLateContext::PlainImpl, }, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index c33219e4700..9f6079ecba4 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -472,7 +472,9 @@ impl<'tcx> Collector<'tcx> { Abi::Fastcall { .. } => { DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) } - // Vectorcall is intentionally not supported at this time. + Abi::Vectorcall { .. } => { + DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) + } _ => { self.tcx.sess.span_fatal( item.span, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 6b0b5ac7da9..40dc4fb052d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1114,7 +1114,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_fn_has_self_parameter(self, id: DefIndex) -> bool { match self.kind(id) { - EntryKind::AssocFn(data) => data.decode(self).has_self, + EntryKind::AssocFn { has_self, .. } => has_self, _ => false, } } @@ -1134,28 +1134,21 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_associated_item(self, id: DefIndex) -> ty::AssocItem { - let def_key = self.def_key(id); - let parent = self.local_def_id(def_key.parent.unwrap()); let name = self.item_name(id); let (kind, container, has_self) = match self.kind(id) { EntryKind::AssocConst(container) => (ty::AssocKind::Const, container, false), - EntryKind::AssocFn(data) => { - let data = data.decode(self); - (ty::AssocKind::Fn, data.container, data.has_self) - } + EntryKind::AssocFn { container, has_self } => (ty::AssocKind::Fn, container, has_self), EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false), - _ => bug!("cannot get associated-item of `{:?}`", def_key), + _ => bug!("cannot get associated-item of `{:?}`", id), }; ty::AssocItem { name, kind, - vis: self.get_visibility(id), - defaultness: container.defaultness(), def_id: self.local_def_id(id), trait_item_def_id: self.get_trait_item_def_id(id), - container: container.with_def_id(parent), + container, fn_has_self_parameter: has_self, } } @@ -1310,19 +1303,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_trait_of_item(self, id: DefIndex) -> Option<DefId> { - let def_key = self.def_key(id); - match def_key.disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), - // Not an associated item - _ => return None, - } - def_key.parent.and_then(|parent_index| match self.kind(parent_index) { - EntryKind::Trait | EntryKind::TraitAlias => Some(self.local_def_id(parent_index)), - _ => None, - }) - } - fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> + 'a { self.root.native_libraries.decode((self, sess)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 6bf237b8ed5..38ce50e8323 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -235,7 +235,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } - trait_of_item => { cdata.get_trait_of_item(def_id.index) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f0886036899..33278367ce3 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1212,14 +1212,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let ast_item = tcx.hir().expect_trait_item(def_id.expect_local()); + self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness); let trait_item = tcx.associated_item(def_id); - let container = match trait_item.defaultness { - hir::Defaultness::Default { has_value: true } => AssocContainer::TraitWithDefault, - hir::Defaultness::Default { has_value: false } => AssocContainer::TraitRequired, - hir::Defaultness::Final => span_bug!(ast_item.span, "traits cannot have final items"), - }; - match trait_item.kind { ty::AssocKind::Const => { let rendered = rustc_hir_pretty::to_string( @@ -1227,7 +1222,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { |s| s.print_trait_item(ast_item), ); - record!(self.tables.kind[def_id] <- EntryKind::AssocConst(container)); + record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::TraitContainer)); record!(self.tables.mir_const_qualif[def_id] <- mir::ConstQualifs::default()); record!(self.tables.rendered_const[def_id] <- rendered); } @@ -1243,14 +1238,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); self.tables.constness.set(def_id.index, hir::Constness::NotConst); - record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData { - container, + record!(self.tables.kind[def_id] <- EntryKind::AssocFn { + container: ty::AssocItemContainer::TraitContainer, has_self: trait_item.fn_has_self_parameter, - }))); + }); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); - record!(self.tables.kind[def_id] <- EntryKind::AssocType(container)); + record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::TraitContainer)); } } match trait_item.kind { @@ -1258,7 +1253,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_item_type(def_id); } ty::AssocKind::Type => { - if trait_item.defaultness.has_value() { + if ast_item.defaultness.has_value() { self.encode_item_type(def_id); } } @@ -1273,23 +1268,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); + self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness); let impl_item = self.tcx.associated_item(def_id); - let container = match impl_item.defaultness { - hir::Defaultness::Default { has_value: true } => AssocContainer::ImplDefault, - hir::Defaultness::Final => AssocContainer::ImplFinal, - hir::Defaultness::Default { has_value: false } => { - span_bug!(ast_item.span, "impl items always have values (currently)") - } - }; - match impl_item.kind { ty::AssocKind::Const => { if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind { let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id); let const_data = self.encode_rendered_const_for_body(body_id); - record!(self.tables.kind[def_id] <- EntryKind::AssocConst(container)); + record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::ImplContainer)); record!(self.tables.mir_const_qualif[def_id] <- qualifs); record!(self.tables.rendered_const[def_id] <- const_data); } else { @@ -1307,13 +1295,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::Constness::NotConst }; self.tables.constness.set(def_id.index, constness); - record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData { - container, + record!(self.tables.kind[def_id] <- EntryKind::AssocFn { + container: ty::AssocItemContainer::ImplContainer, has_self: impl_item.fn_has_self_parameter, - }))); + }); } ty::AssocKind::Type => { - record!(self.tables.kind[def_id] <- EntryKind::AssocType(container)); + record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::ImplContainer)); } } self.encode_item_type(def_id); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 23198a85369..66bdecc30db 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -419,9 +419,9 @@ enum EntryKind { Generator, Trait, Impl, - AssocFn(LazyValue<AssocFnData>), - AssocType(AssocContainer), - AssocConst(AssocContainer), + AssocFn { container: ty::AssocItemContainer, has_self: bool }, + AssocType(ty::AssocItemContainer), + AssocConst(ty::AssocItemContainer), TraitAlias, } @@ -434,47 +434,6 @@ struct VariantData { is_non_exhaustive: bool, } -/// Describes whether the container of an associated item -/// is a trait or an impl and whether, in a trait, it has -/// a default, or an in impl, whether it's marked "default". -#[derive(Copy, Clone, TyEncodable, TyDecodable)] -enum AssocContainer { - TraitRequired, - TraitWithDefault, - ImplDefault, - ImplFinal, -} - -impl AssocContainer { - fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { - match *self { - AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => { - ty::TraitContainer(def_id) - } - - AssocContainer::ImplDefault | AssocContainer::ImplFinal => ty::ImplContainer(def_id), - } - } - - fn defaultness(&self) -> hir::Defaultness { - match *self { - AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false }, - - AssocContainer::TraitWithDefault | AssocContainer::ImplDefault => { - hir::Defaultness::Default { has_value: true } - } - - AssocContainer::ImplFinal => hir::Defaultness::Final, - } - } -} - -#[derive(MetadataEncodable, MetadataDecodable)] -struct AssocFnData { - container: AssocContainer, - has_self: bool, -} - #[derive(TyEncodable, TyDecodable)] struct GeneratorData<'tcx> { layout: mir::GeneratorLayout<'tcx>, @@ -492,7 +451,6 @@ pub fn provide(providers: &mut Providers) { trivially_parameterized_over_tcx! { VariantData, - AssocFnData, EntryKind, RawDefId, TraitImpls, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f7311ebdabf..64e158ba348 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1983,53 +1983,45 @@ impl<'tcx> Debug for Rvalue<'tcx> { } AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { - if let Some(def_id) = def_id.as_local() { - let name = if tcx.sess.opts.unstable_opts.span_free_formats { - let substs = tcx.lift(substs).unwrap(); - format!( - "[closure@{}]", - tcx.def_path_str_with_substs(def_id.to_def_id(), substs), - ) - } else { - let span = tcx.def_span(def_id); - format!( - "[closure@{}]", - tcx.sess.source_map().span_to_diagnostic_string(span) - ) - }; - let mut struct_fmt = fmt.debug_struct(&name); - - // FIXME(project-rfc-2229#48): This should be a list of capture names/places - if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in iter::zip(upvars.keys(), places) { - let var_name = tcx.hir().name(var_id); - struct_fmt.field(var_name.as_str(), place); - } - } - - struct_fmt.finish() + let name = if tcx.sess.opts.unstable_opts.span_free_formats { + let substs = tcx.lift(substs).unwrap(); + format!( + "[closure@{}]", + tcx.def_path_str_with_substs(def_id.to_def_id(), substs), + ) } else { - write!(fmt, "[closure]") + let span = tcx.def_span(def_id); + format!( + "[closure@{}]", + tcx.sess.source_map().span_to_diagnostic_string(span) + ) + }; + let mut struct_fmt = fmt.debug_struct(&name); + + // FIXME(project-rfc-2229#48): This should be a list of capture names/places + if let Some(upvars) = tcx.upvars_mentioned(def_id) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { + let var_name = tcx.hir().name(var_id); + struct_fmt.field(var_name.as_str(), place); + } } + + struct_fmt.finish() }), AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| { - if let Some(def_id) = def_id.as_local() { - let name = format!("[generator@{:?}]", tcx.def_span(def_id)); - let mut struct_fmt = fmt.debug_struct(&name); - - // FIXME(project-rfc-2229#48): This should be a list of capture names/places - if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in iter::zip(upvars.keys(), places) { - let var_name = tcx.hir().name(var_id); - struct_fmt.field(var_name.as_str(), place); - } + let name = format!("[generator@{:?}]", tcx.def_span(def_id)); + let mut struct_fmt = fmt.debug_struct(&name); + + // FIXME(project-rfc-2229#48): This should be a list of capture names/places + if let Some(upvars) = tcx.upvars_mentioned(def_id) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { + let var_name = tcx.hir().name(var_id); + struct_fmt.field(var_name.as_str(), place); } - - struct_fmt.finish() - } else { - write!(fmt, "[generator]") } + + struct_fmt.finish() }), } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 510316c778b..eb90169d0e3 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -18,6 +18,7 @@ use rustc_hir::{self, GeneratorKind}; use rustc_target::abi::VariantIdx; use rustc_ast::Mutability; +use rustc_span::def_id::LocalDefId; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -340,8 +341,11 @@ pub enum FakeReadCause { /// If a closure pattern matches a Place starting with an Upvar, then we introduce a /// FakeRead for that Place outside the closure, in such a case this option would be /// Some(closure_def_id). - /// Otherwise, the value of the optional DefId will be None. - ForMatchedPlace(Option<DefId>), + /// Otherwise, the value of the optional LocalDefId will be None. + // + // We can use LocaDefId here since fake read statements are removed + // before codegen in the `CleanupNonCodegenStatements` pass. + ForMatchedPlace(Option<LocalDefId>), /// A fake read of the RefWithinGuard version of a bind-by-value variable /// in a match guard to ensure that its value hasn't change by the time @@ -365,7 +369,7 @@ pub enum FakeReadCause { /// FakeRead for that Place outside the closure, in such a case this option would be /// Some(closure_def_id). /// Otherwise, the value of the optional DefId will be None. - ForLet(Option<DefId>), + ForLet(Option<LocalDefId>), /// If we have an index expression like /// @@ -796,9 +800,6 @@ pub struct Place<'tcx> { pub projection: &'tcx List<PlaceElem<'tcx>>, } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(Place<'_>, 16); - #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable)] pub enum ProjectionElem<V, T> { @@ -862,11 +863,6 @@ pub enum ProjectionElem<V, T> { /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; -// This type is fairly frequently used, so we shouldn't unintentionally increase -// its size. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PlaceElem<'_>, 24); - /////////////////////////////////////////////////////////////////////////// // Operands @@ -909,9 +905,6 @@ pub enum Operand<'tcx> { Constant(Box<Constant<'tcx>>), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(Operand<'_>, 24); - /////////////////////////////////////////////////////////////////////////// // Rvalues @@ -1063,9 +1056,6 @@ pub enum Rvalue<'tcx> { CopyForDeref(Place<'tcx>), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(Rvalue<'_>, 40); - #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum CastKind { /// An exposing pointer to address cast. A cast between a pointer and an integer type, or @@ -1095,13 +1085,12 @@ pub enum AggregateKind<'tcx> { /// active field index would identity the field `c` Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>), - Closure(DefId, SubstsRef<'tcx>), - Generator(DefId, SubstsRef<'tcx>, hir::Movability), + // Note: We can use LocalDefId since closures and generators a deaggregated + // before codegen. + Closure(LocalDefId, SubstsRef<'tcx>), + Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability), } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(AggregateKind<'_>, 48); - #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum NullOp { /// Returns the size of a value of that type @@ -1165,3 +1154,15 @@ pub enum BinOp { /// The `ptr.offset` operator Offset, } + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + static_assert_size!(AggregateKind<'_>, 48); + static_assert_size!(Operand<'_>, 24); + static_assert_size!(Place<'_>, 16); + static_assert_size!(PlaceElem<'_>, 24); + static_assert_size!(Rvalue<'_>, 40); +} diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index fd3359ea80f..405003156c4 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -205,9 +205,9 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Adt(did, _, substs, _, _) => { tcx.bound_type_of(did).subst(tcx, substs) } - AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), + AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs), AggregateKind::Generator(did, substs, movability) => { - tcx.mk_generator(did, substs, movability) + tcx.mk_generator(did.to_def_id(), substs, movability) } }, Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 466a0fc25f7..d8483e7e409 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -413,12 +413,12 @@ rustc_queries! { } query symbols_for_closure_captures( - key: (LocalDefId, DefId) + key: (LocalDefId, LocalDefId) ) -> Vec<rustc_span::Symbol> { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "symbols for captures of closure `{}` in `{}`", - tcx.def_path_str(key.1), + tcx.def_path_str(key.1.to_def_id()), tcx.def_path_str(key.0.to_def_id()) } } @@ -1147,14 +1147,6 @@ rustc_queries! { separate_provide_extern } - /// Given an `associated_item`, find the trait it belongs to. - /// Return `None` if the `DefId` is not an associated item. - query trait_of_item(associated_item: DefId) -> Option<DefId> { - desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) } - cache_on_disk_if { associated_item.is_local() } - separate_provide_extern - } - query is_ctfe_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 36db8d04918..b856af1d8f8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -27,6 +27,7 @@ use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_target::asm::InlineAsmRegOrRegClass; +use rustc_span::def_id::LocalDefId; use std::fmt; use std::ops::Index; @@ -189,10 +190,6 @@ pub enum StmtKind<'tcx> { }, } -// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr<'_>, 104); - #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] #[derive(TypeFoldable, TypeVisitable)] pub struct LocalVarId(pub hir::HirId); @@ -405,7 +402,7 @@ pub enum ExprKind<'tcx> { }, /// A closure definition. Closure { - closure_id: DefId, + closure_id: LocalDefId, substs: UpvarSubsts<'tcx>, upvars: Box<[ExprId]>, movability: Option<hir::Movability>, @@ -811,3 +808,14 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } } } + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(Block, 56); + rustc_data_structures::static_assert_size!(Expr<'_>, 104); + rustc_data_structures::static_assert_size!(Pat<'_>, 24); + rustc_data_structures::static_assert_size!(Stmt<'_>, 120); +} diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 3c1d0061ae1..2465f8e2533 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -217,7 +217,7 @@ impl<'tcx> Ancestors<'tcx> { self.find_map(|node| { if let Some(item) = node.item(tcx, trait_item_def_id) { if finalizing_node.is_none() { - let is_specializable = item.defaultness.is_default() + let is_specializable = item.defaultness(tcx).is_default() || tcx.impl_defaultness(node.def_id()).is_default(); if !is_specializable { diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index eb732148e3e..c97156ac17f 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -1,6 +1,6 @@ pub use self::AssocItemContainer::*; -use crate::ty; +use crate::ty::{self, DefIdTree}; use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -11,33 +11,8 @@ use super::{TyCtxt, Visibility}; #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)] pub enum AssocItemContainer { - TraitContainer(DefId), - ImplContainer(DefId), -} - -impl AssocItemContainer { - pub fn impl_def_id(&self) -> Option<DefId> { - match *self { - ImplContainer(id) => Some(id), - _ => None, - } - } - - /// Asserts that this is the `DefId` of an associated item declared - /// in a trait, and returns the trait `DefId`. - pub fn assert_trait(&self) -> DefId { - match *self { - TraitContainer(id) => id, - _ => bug!("associated item has wrong container type: {:?}", self), - } - } - - pub fn id(&self) -> DefId { - match *self { - TraitContainer(id) => id, - ImplContainer(id) => id, - } - } + TraitContainer, + ImplContainer, } /// Information about an associated item @@ -46,8 +21,6 @@ pub struct AssocItem { pub def_id: DefId, pub name: Symbol, pub kind: AssocKind, - pub vis: Visibility, - pub defaultness: hir::Defaultness, pub container: AssocItemContainer, /// If this is an item in an impl of a trait then this is the `DefId` of @@ -64,6 +37,36 @@ impl AssocItem { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) } + pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness { + tcx.impl_defaultness(self.def_id) + } + + #[inline] + pub fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility { + tcx.visibility(self.def_id) + } + + #[inline] + pub fn container_id(&self, tcx: TyCtxt<'_>) -> DefId { + tcx.parent(self.def_id) + } + + #[inline] + pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { + match self.container { + AssocItemContainer::ImplContainer => None, + AssocItemContainer::TraitContainer => Some(tcx.parent(self.def_id)), + } + } + + #[inline] + pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { + match self.container { + AssocItemContainer::ImplContainer => Some(tcx.parent(self.def_id)), + AssocItemContainer::TraitContainer => None, + } + } + pub fn signature(&self, tcx: TyCtxt<'_>) -> String { match self.kind { ty::AssocKind::Fn => { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 27b9d27b8bb..0d6c26a5822 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -59,7 +59,7 @@ pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>; /// Given the closure DefId this map provides a map of root variables to minimum /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure. -pub type MinCaptureInformationMap<'tcx> = FxHashMap<DefId, RootVariableMinCaptureList<'tcx>>; +pub type MinCaptureInformationMap<'tcx> = FxHashMap<LocalDefId, RootVariableMinCaptureList<'tcx>>; /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`. /// Used to track the minimum set of `Place`s that need to be captured to support all @@ -253,7 +253,7 @@ impl<'tcx> CapturedPlace<'tcx> { fn symbols_for_closure_captures<'tcx>( tcx: TyCtxt<'tcx>, - def_id: (LocalDefId, DefId), + def_id: (LocalDefId, LocalDefId), ) -> Vec<Symbol> { let typeck_results = tcx.typeck(def_id.0); let captures = typeck_results.closure_min_captures_flattened(def_id.1); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0f98d19820e..0a0f45ce1a0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -570,7 +570,7 @@ pub struct TypeckResults<'tcx> { /// we never capture `t`. This becomes an issue when we build MIR as we require /// information on `t` in order to create place `t.0` and `t.1`. We can solve this /// issue by fake reading `t`. - pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>, + pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>, /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions /// by applying extended parameter rules. @@ -589,7 +589,7 @@ pub struct TypeckResults<'tcx> { /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` /// on closure size. - pub closure_size_eval: FxHashMap<DefId, ClosureSizeProfileData<'tcx>>, + pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>, } impl<'tcx> TypeckResults<'tcx> { @@ -811,7 +811,7 @@ impl<'tcx> TypeckResults<'tcx> { /// by the closure. pub fn closure_min_captures_flattened( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> { self.closure_min_captures .get(&closure_def_id) @@ -1459,11 +1459,11 @@ impl<'tcx> TyCtxt<'tcx> { }; format!( - "{}[{}]{}", + "{}[{:04x}]{}", crate_name, // Don't print the whole stable crate id. That's just // annoying in debug output. - &(format!("{:08x}", stable_crate_id.to_u64()))[..4], + stable_crate_id.to_u64() >> 8 * 6, self.def_path(def_id).to_string_no_crate_verbose() ) } @@ -1668,8 +1668,7 @@ impl<'tcx> TyCtxt<'tcx> { // Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool { - let container_id = - self.associated_item(suitable_region_binding_scope.to_def_id()).container.id(); + let container_id = self.parent(suitable_region_binding_scope.to_def_id()); if self.impl_trait_ref(container_id).is_some() { // For now, we do not try to target impls of traits. This is // because this message is going to suggest that the user diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 91246051316..4b0bc3c1114 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -673,7 +673,7 @@ impl<T> Trait<T> for X { // the associated type or calling a method that returns the associated type". let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type( diag, - assoc.container.id(), + assoc.container_id(self), current_method_ident, proj_ty.item_def_id, values.expected, @@ -844,7 +844,8 @@ fn foo(&self) -> Self::T { String::new() } hir::AssocItemKind::Type => { // FIXME: account for returning some type in a trait fn impl that has // an assoc type as a return type (#72076). - if let hir::Defaultness::Default { has_value: true } = item.defaultness + if let hir::Defaultness::Default { has_value: true } = + self.impl_defaultness(item.id.def_id) { if self.type_of(item.id.def_id) == found { diag.span_label( diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 33a46f809b0..53218225d53 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -460,7 +460,7 @@ impl<'tcx> Instance<'tcx> { && !matches!( tcx.opt_associated_item(def.did), Some(ty::AssocItem { - container: ty::AssocItemContainer::TraitContainer(_), + container: ty::AssocItemContainer::TraitContainer, .. }) ) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 833edd22805..ad78d24e954 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -232,6 +232,10 @@ fn sanity_check_layout<'tcx>( assert!(layout.abi.is_uninhabited()); } + if layout.size.bytes() % layout.align.abi.bytes() != 0 { + bug!("size is not a multiple of align, in the following layout:\n{layout:#?}"); + } + if cfg!(debug_assertions) { fn check_layout_abi<'tcx>(tcx: TyCtxt<'tcx>, layout: Layout<'tcx>) { match layout.abi() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index da9d51a29b1..1978f84c137 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1945,7 +1945,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> { self.associated_items(id) .in_definition_order() - .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value()) + .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) } /// Look up the name of a definition across crates. This does not look at HIR. @@ -2191,13 +2191,29 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_ref(def_id).map(|tr| tr.def_id) } + /// If the given `DefId` describes an item belonging to a trait, + /// returns the `DefId` of the trait that the trait item belongs to; + /// otherwise, returns `None`. + pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> { + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { + let parent = self.parent(def_id); + if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) { + return Some(parent); + } + } + None + } + /// If the given `DefId` describes a method belonging to an impl, returns the /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { - self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { - TraitContainer(_) => None, - ImplContainer(def_id) => Some(def_id), - }) + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { + let parent = self.parent(def_id); + if let DefKind::Impl = self.def_kind(parent) { + return Some(parent); + } + } + None } /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 411d5c55829..fb0a4b4e8f4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1179,13 +1179,14 @@ pub struct ProjectionTy<'tcx> { /// The `DefId` of the `TraitItem` for the associated type `N`. /// /// Note that this is not the `DefId` of the `TraitRef` containing this - /// associated type, which is in `tcx.associated_item(item_def_id).container`. + /// associated type, which is in `tcx.associated_item(item_def_id).container`, + /// aka. `tcx.parent(item_def_id).unwrap()`. pub item_def_id: DefId, } impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - tcx.associated_item(self.item_def_id).container.id() + tcx.parent(self.item_def_id) } /// Extracts the underlying trait reference and own substs from this projection. @@ -1195,7 +1196,7 @@ impl<'tcx> ProjectionTy<'tcx> { &self, tcx: TyCtxt<'tcx>, ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - let def_id = tcx.associated_item(self.item_def_id).container.id(); + let def_id = tcx.parent(self.item_def_id); let trait_generics = tcx.generics_of(def_id); ( ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) }, @@ -1433,7 +1434,7 @@ impl<'tcx> ExistentialProjection<'tcx> { /// then this function would return an `exists T. T: Iterator` existential trait /// reference. pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - let def_id = tcx.associated_item(self.item_def_id).container.id(); + let def_id = tcx.parent(self.item_def_id); let subst_count = tcx.generics_of(def_id).count() - 1; let substs = tcx.intern_substs(&self.substs[..subst_count]); ty::ExistentialTraitRef { def_id, substs } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4d2f69b23fa..4b5bf80c071 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -402,7 +402,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(dtor) => dtor.did, }; - let impl_def_id = self.associated_item(dtor).container.id(); + let impl_def_id = self.parent(dtor); let impl_generics = self.generics_of(impl_def_id); // We have a destructor - all the parameters that are not diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index e88f9dc1f08..0c06aad4e44 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -3,7 +3,7 @@ use crate::build::expr::category::Category; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::hir::place::Projection as HirProjection; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; @@ -58,7 +58,7 @@ pub(crate) enum PlaceBase { /// HirId of the upvar var_hir_id: LocalVarId, /// DefId of the closure - closure_def_id: DefId, + closure_def_id: LocalDefId, /// The trait closure implements, `Fn`, `FnMut`, `FnOnce` closure_kind: ty::ClosureKind, }, @@ -176,7 +176,7 @@ fn compute_capture_idx<'tcx>( fn find_capture_matching_projections<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, var_hir_id: LocalVarId, - closure_def_id: DefId, + closure_def_id: LocalDefId, projections: &[PlaceElem<'tcx>], ) -> Option<(usize, &'a ty::CapturedPlace<'tcx>)> { let closure_min_captures = typeck_results.closure_min_captures.get(&closure_def_id)?; @@ -242,7 +242,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( }; // We won't be building MIR if the closure wasn't local - let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id); let closure_ty = typeck_results.node_type(closure_hir_id); let substs = match closure_ty.kind() { @@ -626,11 +626,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_captured_upvar( &mut self, block: BasicBlock, - closure_expr_id: LocalDefId, + closure_def_id: LocalDefId, var_hir_id: LocalVarId, ) -> BlockAnd<PlaceBuilder<'tcx>> { let closure_ty = - self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_expr_id)); + self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_def_id)); let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() { self.infcx.closure_kind(closure_substs).unwrap() @@ -639,11 +639,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty::ClosureKind::FnOnce }; - block.and(PlaceBuilder::from(PlaceBase::Upvar { - var_hir_id, - closure_def_id: closure_expr_id.to_def_id(), - closure_kind, - })) + block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id, closure_kind })) } /// Lower an index expression diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 7ae26cccb38..12b8ceede0f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -672,7 +672,7 @@ where Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { builder.args_and_body( START_BLOCK, - fn_def.did.to_def_id(), + fn_def.did, &arguments, arg_scope, &thir[expr], @@ -895,7 +895,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn args_and_body( &mut self, mut block: BasicBlock, - fn_def_id: DefId, + fn_def_id: LocalDefId, arguments: &[ArgInfo<'tcx>], argument_scope: region::Scope, expr: &Expr<'tcx>, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 55ad83f8975..864caf0ba31 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -408,7 +408,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { movability: _, fake_reads: _, } => { - let closure_id = closure_id.expect_local(); let closure_def = if let Some((did, const_param_id)) = ty::WithOptConstParam::try_lookup(closure_id, self.tcx) { diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index d21a8c4f9b9..54d549fd66c 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -1,10 +1,10 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; -use rustc_hir::intravisit::FnKind; +use rustc_hir::def::DefKind; use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; -use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; +use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; use rustc_span::Span; use std::ops::ControlFlow; @@ -12,18 +12,11 @@ use std::ops::ControlFlow; pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id().expect_local(); - if let Some(fn_kind) = tcx.hir().get_by_def_id(def_id).fn_kind() { - if let FnKind::Closure = fn_kind { - // closures can't recur, so they don't matter. - return; - } - + if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) { // If this is trait/impl method, extract the trait's substs. - let trait_substs = match tcx.opt_associated_item(def_id.to_def_id()) { - Some(AssocItem { - container: AssocItemContainer::TraitContainer(trait_def_id), .. - }) => { - let trait_substs_count = tcx.generics_of(*trait_def_id).count(); + let trait_substs = match tcx.trait_of_item(def_id.to_def_id()) { + Some(trait_def_id) => { + let trait_substs_count = tcx.generics_of(trait_def_id).count(); &InternalSubsts::identity_for_item(tcx, def_id.to_def_id())[..trait_substs_count] } _ => &[], @@ -41,8 +34,8 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { vis.reachable_recursive_calls.sort(); + let sp = tcx.def_span(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span_with_body(hir_id)); tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| { let mut db = lint.build("function cannot return without recursing"); db.span_label(sp, "cannot return without recursing"); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 4eb3607e9cc..985601712c4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -523,6 +523,7 @@ impl<'tcx> Cx<'tcx> { span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } }; + let def_id = def_id.expect_local(); let upvars = self .typeck_results diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 13ae8a1cd3e..d564f480166 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -129,7 +129,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { } &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = - self.tcx.unsafety_check_result(def_id.expect_local()); + self.tcx.unsafety_check_result(def_id); self.register_violations( violations, used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)), diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index d3aaad46015..847e64dc2a2 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -17,8 +17,8 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In return; }; - let closure_def_id = closure_instance.def_id(); - let typeck_results = tcx.typeck(closure_def_id.expect_local()); + let closure_def_id = closure_instance.def_id().expect_local(); + let typeck_results = tcx.typeck(closure_def_id); if typeck_results.closure_size_eval.contains_key(&closure_def_id) { let param_env = ty::ParamEnv::reveal_all(); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index e9701ec2d7f..848e142e59c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -22,6 +22,13 @@ mod unicode_chars; use unescape_error_reporting::{emit_unescape_error, escaped_char}; +// This type is used a lot. Make sure it doesn't unintentionally get bigger. +// +// This assertion is in this crate, rather than in `rustc_lexer`, because that +// crate cannot depend on `rustc_data_structures`. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12); + #[derive(Clone, Debug)] pub struct UnmatchedBrace { pub expected_delim: Delimiter, @@ -37,8 +44,7 @@ pub(crate) fn parse_token_trees<'a>( start_pos: BytePos, override_span: Option<Span>, ) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) { - StringReader { sess, start_pos, pos: start_pos, end_src_index: src.len(), src, override_span } - .into_token_trees() + StringReader { sess, start_pos, pos: start_pos, src, override_span }.into_token_trees() } struct StringReader<'a> { @@ -47,8 +53,6 @@ struct StringReader<'a> { start_pos: BytePos, /// The absolute offset within the source_map of the current character. pos: BytePos, - /// Stop reading src at this index. - end_src_index: usize, /// Source text to tokenize. src: &'a str, override_span: Option<Span>, @@ -64,20 +68,17 @@ impl<'a> StringReader<'a> { let mut spacing = Spacing::Joint; // Skip `#!` at the start of the file - let start_src_index = self.src_index(self.pos); - let text: &str = &self.src[start_src_index..self.end_src_index]; - let is_beginning_of_file = self.pos == self.start_pos; - if is_beginning_of_file { - if let Some(shebang_len) = rustc_lexer::strip_shebang(text) { - self.pos = self.pos + BytePos::from_usize(shebang_len); - spacing = Spacing::Alone; - } + if self.pos == self.start_pos + && let Some(shebang_len) = rustc_lexer::strip_shebang(self.src) + { + self.pos = self.pos + BytePos::from_usize(shebang_len); + spacing = Spacing::Alone; } // Skip trivial (whitespace & comments) tokens loop { let start_src_index = self.src_index(self.pos); - let text: &str = &self.src[start_src_index..self.end_src_index]; + let text: &str = &self.src[start_src_index..]; if text.is_empty() { let span = self.mk_sp(self.pos, self.pos); @@ -87,7 +88,7 @@ impl<'a> StringReader<'a> { let token = rustc_lexer::first_token(text); let start = self.pos; - self.pos = self.pos + BytePos::from_usize(token.len); + self.pos = self.pos + BytePos(token.len); debug!("next_token: {:?}({:?})", token.kind, self.str_from(start)); @@ -239,7 +240,7 @@ impl<'a> StringReader<'a> { token::Ident(sym, false) } rustc_lexer::TokenKind::Literal { kind, suffix_start } => { - let suffix_start = start + BytePos(suffix_start as u32); + let suffix_start = start + BytePos(suffix_start); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); let suffix = if suffix_start < self.pos { let string = self.str_from(suffix_start); @@ -404,15 +405,21 @@ impl<'a> StringReader<'a> { } (token::ByteStr, Mode::ByteStr, 2, 1) // b" " } - rustc_lexer::LiteralKind::RawStr { n_hashes, err } => { - self.report_raw_str_error(start, err); - let n = u32::from(n_hashes); - (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## + rustc_lexer::LiteralKind::RawStr { n_hashes } => { + if let Some(n_hashes) = n_hashes { + let n = u32::from(n_hashes); + (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## + } else { + self.report_raw_str_error(start, 1); + } } - rustc_lexer::LiteralKind::RawByteStr { n_hashes, err } => { - self.report_raw_str_error(start, err); - let n = u32::from(n_hashes); - (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## + rustc_lexer::LiteralKind::RawByteStr { n_hashes } => { + if let Some(n_hashes) = n_hashes { + let n = u32::from(n_hashes); + (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## + } else { + self.report_raw_str_error(start, 2); + } } rustc_lexer::LiteralKind::Int { base, empty_int } => { return if empty_int { @@ -483,17 +490,17 @@ impl<'a> StringReader<'a> { &self.src[self.src_index(start)..self.src_index(end)] } - fn report_raw_str_error(&self, start: BytePos, opt_err: Option<RawStrError>) { - match opt_err { - Some(RawStrError::InvalidStarter { bad_char }) => { + fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! { + match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) { + Err(RawStrError::InvalidStarter { bad_char }) => { self.report_non_started_raw_string(start, bad_char) } - Some(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self + Err(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self .report_unterminated_raw_string(start, expected, possible_terminator_offset, found), - Some(RawStrError::TooManyDelimiters { found }) => { + Err(RawStrError::TooManyDelimiters { found }) => { self.report_too_many_hashes(start, found) } - None => (), + Ok(()) => panic!("no error found for supposedly invalid raw string literal"), } } @@ -510,9 +517,9 @@ impl<'a> StringReader<'a> { fn report_unterminated_raw_string( &self, start: BytePos, - n_hashes: usize, - possible_offset: Option<usize>, - found_terminators: usize, + n_hashes: u32, + possible_offset: Option<u32>, + found_terminators: u32, ) -> ! { let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( self.mk_sp(start, start), @@ -525,7 +532,7 @@ impl<'a> StringReader<'a> { if n_hashes > 0 { err.note(&format!( "this raw string should be terminated with `\"{}`", - "#".repeat(n_hashes) + "#".repeat(n_hashes as usize) )); } @@ -536,7 +543,7 @@ impl<'a> StringReader<'a> { err.span_suggestion( span, "consider terminating the string here", - "#".repeat(n_hashes), + "#".repeat(n_hashes as usize), Applicability::MaybeIncorrect, ); } @@ -637,7 +644,7 @@ impl<'a> StringReader<'a> { } } - fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! { + fn report_too_many_hashes(&self, start: BytePos, found: u32) -> ! { self.fatal_span_( start, self.pos, diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 0816bc8deb6..aa70912dcde 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -277,6 +277,7 @@ struct TokenStreamBuilder { } impl TokenStreamBuilder { + #[inline(always)] fn push(&mut self, tree: TokenTree) { if let Some(TokenTree::Token(prev_token, Spacing::Joint)) = self.buf.last() && let TokenTree::Token(token, joint) = &tree @@ -284,9 +285,9 @@ impl TokenStreamBuilder { { self.buf.pop(); self.buf.push(TokenTree::Token(glued, *joint)); - return; + } else { + self.buf.push(tree) } - self.buf.push(tree); } fn into_token_stream(self) -> TokenStream { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c0f661f7dbb..e473f4d30cf 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1391,8 +1391,6 @@ impl<'a> Parser<'a> { } else if self.is_do_yeet() { self.parse_yeet_expr(attrs) } else if self.check_keyword(kw::Let) { - self.manage_let_chains_context(); - self.bump(); self.parse_let_expr(attrs) } else if self.eat_keyword(kw::Underscore) { Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) @@ -2342,32 +2340,24 @@ impl<'a> Parser<'a> { /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> { - self.with_let_management(true, |local_self| { - local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None) - }) + self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None) } - // Checks if `let` is in an invalid position like `let x = let y = 1;` or - // if the current `let` is in a let_chains context but nested in another - // expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`. - // - // This method expects that the current token is `let`. - fn manage_let_chains_context(&mut self) { - debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _))); - let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed - && !matches!( - self.prev_token.kind, - TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _) - ); - if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr { + /// Parses a `let $pat = $expr` pseudo-expression. + fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { + // This is a *approximate* heuristic that detects if `let` chains are + // being parsed in the right position. It's approximate because it + // doesn't deny all invalid `let` expressions, just completely wrong usages. + let not_in_chain = !matches!( + self.prev_token.kind, + TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _) + ); + if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain { self.struct_span_err(self.token.span, "expected expression, found `let` statement") .emit(); } - } - /// Parses a `let $pat = $expr` pseudo-expression. - /// The `let` token has already been eaten. - fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { + self.bump(); // Eat `let` token let lo = self.prev_token.span; let pat = self.parse_pat_allow_top_alt( None, @@ -2687,7 +2677,9 @@ impl<'a> Parser<'a> { // `&&` tokens. fn check_let_expr(expr: &Expr) -> bool { match expr.kind { - ExprKind::Binary(_, ref lhs, ref rhs) => check_let_expr(lhs) || check_let_expr(rhs), + ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => { + check_let_expr(lhs) || check_let_expr(rhs) + } ExprKind::Let(..) => true, _ => false, } @@ -2703,9 +2695,8 @@ impl<'a> Parser<'a> { )?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; - let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?; - let has_let_expr = check_let_expr(&cond); - if has_let_expr { + let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?; + if check_let_expr(&cond) { let span = if_span.to(cond.span); this.sess.gated_spans.gate(sym::if_let_guard, span); } @@ -3279,17 +3270,4 @@ impl<'a> Parser<'a> { Ok((res, trailing)) }) } - - // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then - // sets the internal `let_expr_allowed` back to its original value. - fn with_let_management<T>( - &mut self, - let_expr_allowed: bool, - f: impl FnOnce(&mut Self) -> T, - ) -> T { - let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed); - let rslt = f(self); - self.let_expr_allowed = last_let_expr_allowed; - rslt - } } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1ac8b224248..0c523ad22c2 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -47,6 +47,7 @@ bitflags::bitflags! { const STMT_EXPR = 1 << 0; const NO_STRUCT_LITERAL = 1 << 1; const CONST_EXPR = 1 << 2; + const ALLOW_LET = 1 << 3; } } @@ -147,15 +148,12 @@ pub struct Parser<'a> { /// This allows us to recover when the user forget to add braces around /// multiple statements in the closure body. pub current_closure: Option<ClosureSpans>, - /// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid - /// but `[1, 2, 3][let _ = ()]` is not. - let_expr_allowed: bool, } // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 336); +rustc_data_structures::static_assert_size!(Parser<'_>, 328); /// Stores span information about a closure. #[derive(Clone)] @@ -462,7 +460,6 @@ impl<'a> Parser<'a> { inner_attr_ranges: Default::default(), }, current_closure: None, - let_expr_allowed: false, }; // Make parser point to the first token. diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index f1a81b65329..70518284cf9 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -97,7 +97,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { // If the function belongs to a trait, then it must enable the const_trait_impl // feature to use that trait function (with a const default body). - if tcx.trait_of_item(def_id).is_some() { + if tcx.trait_of_item(def_id.to_def_id()).is_some() { return true; } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index eed3e1579a2..461dd52b9f2 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -519,7 +519,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> { let typeck_results = ir.tcx.typeck(body_owner); let param_env = ir.tcx.param_env(body_owner); - let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner.to_def_id()); + let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner); let closure_ln = ir.add_live_node(ClosureNode); let exit_ln = ir.add_live_node(ExitNode); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 390d6f5a856..7d4ee832974 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -212,7 +212,7 @@ where // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type, // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { - if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if let Some(impl_def_id) = assoc_item.impl_container(tcx) { tcx.type_of(impl_def_id).visit_with(self)?; } } @@ -734,11 +734,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.def_id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { + let tcx = self.tcx; let mut reach = self.reach(trait_item_ref.id.def_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type - && !trait_item_ref.defaultness.has_value() + && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value() { // No type to visit. } else { @@ -1754,8 +1755,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { || self.in_assoc_ty || self.tcx.resolutions(()).has_pub_restricted { - let vis_span = - self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)); + let vis_span = self.tcx.def_span(def_id); if kind == "trait" { self.tcx.sess.emit_err(InPublicInterfaceTraits { span, @@ -1840,14 +1840,13 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { &self, def_id: LocalDefId, assoc_item_kind: AssocItemKind, - defaultness: hir::Defaultness, vis: ty::Visibility, ) { let mut check = self.check(def_id, vis); let (check_ty, is_assoc_ty) = match assoc_item_kind { AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false), - AssocItemKind::Type => (defaultness.has_value(), true), + AssocItemKind::Type => (self.tcx.impl_defaultness(def_id).has_value(), true), }; check.in_assoc_ty = is_assoc_ty; check.generics().predicates(); @@ -1879,7 +1878,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { self.check_assoc_item( trait_item_ref.id.def_id, trait_item_ref.kind, - trait_item_ref.defaultness, item_visibility, ); @@ -1952,7 +1950,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { self.check_assoc_item( impl_item_ref.id.def_id, impl_item_ref.kind, - impl_item_ref.defaultness, impl_item_vis, ); } diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 54774314313..49175e97f41 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -191,6 +191,16 @@ impl Key for (LocalDefId, DefId) { } } +impl Key for (LocalDefId, LocalDefId) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} + impl Key for (DefId, Option<Ident>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 9f5779194af..6d2aff38172 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,4 +1,3 @@ -use crate::dep_graph::DepContext; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryStackFrame}; use rustc_hir::def::DefKind; @@ -536,17 +535,13 @@ pub(crate) fn report_cycle<'a>( ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { assert!(!stack.is_empty()); - let fix_span = |span: Span, query: &QueryStackFrame| { - sess.source_map().guess_head_span(query.default_span(span)) - }; - - let span = fix_span(stack[1 % stack.len()].span, &stack[0].query); + let span = stack[0].query.default_span(stack[1 % stack.len()].span); let mut err = struct_span_err!(sess, span, E0391, "cycle detected when {}", stack[0].query.description); for i in 1..stack.len() { let query = &stack[i].query; - let span = fix_span(stack[(i + 1) % stack.len()].span, query); + let span = query.default_span(stack[(i + 1) % stack.len()].span); err.span_note(span, &format!("...which requires {}...", query.description)); } @@ -577,7 +572,7 @@ pub(crate) fn report_cycle<'a>( } if let Some((span, query)) = usage { - err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description)); + err.span_note(query.default_span(span), &format!("cycle used when {}", query.description)); } err @@ -606,8 +601,7 @@ pub fn print_query_stack<CTX: QueryContext>( Level::FailureNote, &format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description), ); - diag.span = - tcx.dep_context().sess().source_map().guess_head_span(query_info.job.span).into(); + diag.span = query_info.job.span.into(); handler.force_print_diagnostic(diag); current_query = query_info.job.parent; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 22a307a15ed..8839fb1a151 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1587,11 +1587,7 @@ impl<'a> Resolver<'a> { }; let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate { LOCAL_CRATE => self.opt_span(def_id), - _ => Some( - self.session - .source_map() - .guess_head_span(self.cstore().get_span_untracked(def_id, self.session)), - ), + _ => Some(self.cstore().get_span_untracked(def_id, self.session)), }); if let Some(def_span) = def_span { if span.overlaps(def_span) { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6b49c6b1ac6..2b1f2b88ec4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -136,12 +136,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn def_span(&self, def_id: DefId) -> Option<Span> { match def_id.krate { LOCAL_CRATE => self.r.opt_span(def_id), - _ => Some( - self.r - .session - .source_map() - .guess_head_span(self.r.cstore().get_span_untracked(def_id, self.r.session)), - ), + _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.session)), } } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 0a0c674d179..a1a2040bbca 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -564,8 +564,8 @@ impl<'tcx> SaveContext<'tcx> { return None; }; let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { - ty::ImplContainer(_) => (Some(method_id), None), - ty::TraitContainer(_) => (None, Some(method_id)), + ty::ImplContainer => (Some(method_id), None), + ty::TraitContainer => (None, Some(method_id)), }; let sub_span = seg.ident.span; filter!(self.span_utils, sub_span); @@ -697,7 +697,7 @@ impl<'tcx> SaveContext<'tcx> { } Res::Def(HirDefKind::AssocFn, decl_id) => { let def_id = if decl_id.is_local() { - if self.tcx.associated_item(decl_id).defaultness.has_value() { + if self.tcx.impl_defaultness(decl_id).has_value() { Some(decl_id) } else { None diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 70f942a6508..6a8298605a2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1159,20 +1159,6 @@ impl CrateCheckConfig { self.fill_well_known_names(); self.fill_well_known_values(); } - - /// Fills a `CrateCheckConfig` with configuration names and values that are actually active. - pub fn fill_actual(&mut self, cfg: &CrateConfig) { - for &(k, v) in cfg { - if let Some(names_valid) = &mut self.names_valid { - names_valid.insert(k); - } - if let Some(v) = v { - self.values_valid.entry(k).and_modify(|values| { - values.insert(v); - }); - } - } - } } pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6495339eaf1..1827f1c208d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -393,8 +393,7 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin"; - pub const parse_location_detail: &str = - "comma separated list of location details to track: `file`, `line`, or `column`"; + pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`"; pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; @@ -551,6 +550,9 @@ mod parse { ld.line = false; ld.file = false; ld.column = false; + if v == "none" { + return true; + } for s in v.split(',') { match s { "file" => ld.file = true, @@ -1374,8 +1376,9 @@ options! { llvm_time_trace: bool = (false, parse_bool, [UNTRACKED], "generate JSON tracing data file from LLVM data (default: no)"), location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED], - "comma separated list of location details to be tracked when using caller_location \ - valid options are `file`, `line`, and `column` (default: all)"), + "what location details should be tracked when using caller_location, either \ + `none`, or a comma separated list of location details, for which \ + valid options are `file`, `line`, and `column` (default: `file,line,column`)"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index ca1d1302ec6..577126a95cc 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -669,8 +669,10 @@ impl<'a, Ty> FnAbi<'a, Ty> { match &cx.target_spec().arch[..] { "x86" => { - let flavor = if let spec::abi::Abi::Fastcall { .. } = abi { - x86::Flavor::Fastcall + let flavor = if let spec::abi::Abi::Fastcall { .. } + | spec::abi::Abi::Vectorcall { .. } = abi + { + x86::Flavor::FastcallOrVectorcall } else { x86::Flavor::General }; diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index d169087dfbd..c7d59baf919 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -5,7 +5,7 @@ use crate::spec::HasTargetSpec; #[derive(PartialEq)] pub enum Flavor { General, - Fastcall, + FastcallOrVectorcall, } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor) @@ -60,9 +60,9 @@ where } } - if flavor == Flavor::Fastcall { + if flavor == Flavor::FastcallOrVectorcall { // Mark arguments as InReg like clang does it, - // so our fastcall is compatible with C/C++ fastcall. + // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall. // Clang reference: lib/CodeGen/TargetInfo.cpp // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs() diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b35502d9ee4..d4d5674e246 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1279,13 +1279,14 @@ impl<'a> fmt::Debug for LayoutS<'a> { // This is how `Layout` used to print before it become // `Interned<LayoutS>`. We print it like this to avoid having to update // expected output in a lot of tests. + let LayoutS { size, align, abi, fields, largest_niche, variants } = self; f.debug_struct("Layout") - .field("fields", &self.fields) - .field("variants", &self.variants) - .field("abi", &self.abi) - .field("largest_niche", &self.largest_niche) - .field("align", &self.align) - .field("size", &self.size) + .field("size", size) + .field("align", align) + .field("abi", abi) + .field("fields", fields) + .field("largest_niche", largest_niche) + .field("variants", variants) .finish() } } diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 5fcaa52d417..4b575ea660a 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -23,8 +23,6 @@ pub fn codegen_fulfill_obligation<'tcx>( tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { - // Remove any references to regions; this helps improve caching. - let trait_ref = tcx.erase_regions(trait_ref); // We expect the input to be fully normalized. debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 7ee3fe844b5..e442c5c9189 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2129,7 +2129,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } ] = path.segments && data.trait_ref.def_id == *trait_id - && self.tcx.trait_of_item(item_id) == Some(*trait_id) + && self.tcx.trait_of_item(*item_id) == Some(*trait_id) && !self.is_tainted_by_errors() { let (verb, noun) = match self.tcx.associated_item(item_id).kind { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 7e8872d9018..e6907637c57 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -223,8 +223,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(def) = aty.ty_adt_def() { // We also want to be able to select the slice's type's original // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did()).to_string(); - flags.push((sym::_Self, Some(format!("[{type_string}]")))); + flags.push((sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did()))))); } if aty.is_integral() { flags.push((sym::_Self, Some("[{integral}]".to_string()))); @@ -242,10 +241,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(def) = aty.ty_adt_def() { // We also want to be able to select the array's type's original // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did()).to_string(); - flags.push((sym::_Self, Some(format!("[{type_string}; _]")))); + let def_ty = self.tcx.type_of(def.did()); + flags.push((sym::_Self, Some(format!("[{def_ty}; _]")))); if let Some(n) = len { - flags.push((sym::_Self, Some(format!("[{type_string}; {n}]")))); + flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]")))); } } if aty.is_integral() { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b2eb8fdf8a5..219413121d8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1946,7 +1946,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); let original_span = err.span.primary_span().unwrap(); - let original_span = self.tcx.sess.source_map().guess_head_span(original_span); let mut span = MultiSpan::from_span(original_span); let message = outer_generator @@ -2715,7 +2714,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(ident) = self .tcx .opt_associated_item(trait_item_def_id) - .and_then(|i| self.tcx.opt_item_ident(i.container.id())) + .and_then(|i| self.tcx.opt_item_ident(i.container_id(self.tcx))) { assoc_span.push_span_label(ident.span, "in this trait"); } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 2921ce0ffef..612f5130908 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -690,7 +690,7 @@ fn receiver_is_dispatchable<'tcx>( // U: Trait<Arg1, ..., ArgN> let trait_predicate = { let substs = - InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| { + InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| { if param.index == 0 { unsized_self_ty.into() } else { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9de4d3a646c..d22465db85b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1988,7 +1988,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( return Progress { term: tcx.ty_error().into(), obligations: nested }; }; - if !assoc_ty.item.defaultness.has_value() { + if !assoc_ty.item.defaultness(tcx).has_value() { // This means that the impl is missing a definition for the // associated type. This error will be reported by the type // checker method `check_impl_items_against_trait`, so here we @@ -2089,7 +2089,11 @@ fn assoc_def( return Ok(specialization_graph::LeafDef { item: *item, defining_node: impl_node, - finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) }, + finalizing_node: if item.defaultness(tcx).is_default() { + None + } else { + Some(impl_node) + }, }); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 3170b29ee69..b9259196c48 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -358,7 +358,8 @@ pub fn generator_trait_ref_and_outputs<'tcx>( } pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { - assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final() + assoc_item.defaultness(tcx).is_final() + && tcx.impl_defaultness(assoc_item.container_id(tcx)).is_final() } pub enum TupleArgumentsFlag { diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 497819ce5c5..14a60ace441 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -8,9 +8,7 @@ use rustc_middle::traits::ChalkRustInterner as RustInterner; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{ - self, AssocItemContainer, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, -}; +use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; use rustc_ast::ast; use rustc_attr as attr; @@ -74,7 +72,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t ) -> Arc<chalk_solve::rust_ir::AssociatedTyDatum<RustInterner<'tcx>>> { let def_id = assoc_type_id.0; let assoc_item = self.interner.tcx.associated_item(def_id); - let AssocItemContainer::TraitContainer(trait_def_id) = assoc_item.container else { + let Some(trait_def_id) = assoc_item.trait_container(self.interner.tcx) else { unimplemented!("Not possible??"); }; match assoc_item.kind { @@ -455,7 +453,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t ) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> { let def_id = associated_ty_id.0; let assoc_item = self.interner.tcx.associated_item(def_id); - let impl_id = assoc_item.container.id(); + let impl_id = assoc_item.container_id(self.interner.tcx); match assoc_item.kind { AssocKind::Type => {} _ => unimplemented!("Not possible??"), diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 4142c999ca7..515a73ead77 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, TyCtxt}; pub fn provide(providers: &mut ty::query::Providers) { @@ -9,7 +9,6 @@ pub fn provide(providers: &mut ty::query::Providers) { associated_item_def_ids, associated_items, impl_item_implementor_ids, - trait_of_item, ..*providers }; } @@ -40,16 +39,6 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId .collect() } -/// If the given `DefId` describes an item belonging to a trait, -/// returns the `DefId` of the trait that the trait item belongs to; -/// otherwise, returns `None`. -fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { - tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container { - ty::TraitContainer(def_id) => Some(def_id), - ty::ImplContainer(_) => None, - }) -} - fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_def_id = tcx.hir().get_parent_item(id); @@ -59,8 +48,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) { - let assoc_item = - associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref); + let assoc_item = associated_item_from_impl_item_ref(impl_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); return assoc_item; } @@ -70,8 +58,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) { - let assoc_item = - associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref); + let assoc_item = associated_item_from_trait_item_ref(trait_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); return assoc_item; } @@ -87,11 +74,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { ) } -fn associated_item_from_trait_item_ref( - tcx: TyCtxt<'_>, - parent_def_id: LocalDefId, - trait_item_ref: &hir::TraitItemRef, -) -> ty::AssocItem { +fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { let def_id = trait_item_ref.id.def_id; let (kind, has_self) = match trait_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), @@ -102,20 +85,14 @@ fn associated_item_from_trait_item_ref( ty::AssocItem { name: trait_item_ref.ident.name, kind, - vis: tcx.visibility(def_id), - defaultness: trait_item_ref.defaultness, def_id: def_id.to_def_id(), trait_item_def_id: Some(def_id.to_def_id()), - container: ty::TraitContainer(parent_def_id.to_def_id()), + container: ty::TraitContainer, fn_has_self_parameter: has_self, } } -fn associated_item_from_impl_item_ref( - tcx: TyCtxt<'_>, - parent_def_id: LocalDefId, - impl_item_ref: &hir::ImplItemRef, -) -> ty::AssocItem { +fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { let def_id = impl_item_ref.id.def_id; let (kind, has_self) = match impl_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), @@ -126,11 +103,9 @@ fn associated_item_from_impl_item_ref( ty::AssocItem { name: impl_item_ref.ident.name, kind, - vis: tcx.visibility(def_id), - defaultness: impl_item_ref.defaultness, def_id: def_id.to_def_id(), trait_item_def_id: impl_item_ref.trait_item_def_id, - container: ty::ImplContainer(parent_def_id.to_def_id()), + container: ty::ImplContainer, fn_has_self_parameter: has_self, } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 979e997f244..bd1d568cd9a 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -281,7 +281,7 @@ fn resolve_associated_item<'tcx>( } // If the item does not have a value, then we cannot return an instance. - if !leaf_def.item.defaultness.has_value() { + if !leaf_def.item.defaultness(tcx).has_value() { return Ok(None); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index b1af3051719..7007e76b86e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -70,11 +70,13 @@ fn sized_constraint_for_ty<'tcx>( } fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { - let item = tcx.hir().expect_item(def_id.expect_local()); - if let hir::ItemKind::Impl(impl_) = &item.kind { - impl_.defaultness - } else { - bug!("`impl_defaultness` called on {:?}", item); + match tcx.hir().get_by_def_id(def_id.expect_local()) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.defaultness, + hir::Node::ImplItem(hir::ImplItem { defaultness, .. }) + | hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness, + node => { + bug!("`impl_defaultness` called on {:?}", node); + } } } diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index 99a8101dc96..ff39bf36129 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -255,7 +255,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_bound_spans.push(*span); } for assoc_item in items { - let trait_def_id = assoc_item.container.id(); + let trait_def_id = assoc_item.container_id(tcx); names.push(format!( "`{}` (from trait `{}`)", assoc_item.name, @@ -321,7 +321,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut dupes = false; for item in assoc_items { let prefix = if names[&item.name] > 1 { - let trait_def_id = item.container.id(); + let trait_def_id = item.container_id(tcx); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) } else { @@ -376,7 +376,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut label = vec![]; for item in assoc_items { let postfix = if names[&item.name] > 1 { - let trait_def_id = item.container.id(); + let trait_def_id = item.container_id(tcx); format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) } else { String::new() diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 444f0fdd45a..8a5c7fee697 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1141,7 +1141,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .or_else(|| find_item_of_kind(ty::AssocKind::Const)) .expect("missing associated type"); - if !assoc_item.vis.is_accessible_from(def_scope, tcx) { + if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { tcx.sess .struct_span_err( binding.span, @@ -1160,7 +1160,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: binding.span, prev_span: *prev_span, item_name: binding.item_name, - def_path: tcx.def_path_str(assoc_item.container.id()), + def_path: tcx.def_path_str(assoc_item.container_id(tcx)), }); }) .or_insert(binding.span); @@ -1997,7 +1997,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let ty = self.normalize_ty(span, ty); let kind = DefKind::AssocTy; - if !item.vis.is_accessible_from(def_scope, tcx) { + if !item.visibility(tcx).is_accessible_from(def_scope, tcx) { let kind = kind.descr(item.def_id); let msg = format!("{} `{}` is private", kind, assoc_ident); tcx.sess diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index df315b8a3bc..1b13c98e4c3 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -293,6 +293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn if_cause( &self, span: Span, + cond_span: Span, then_expr: &'tcx hir::Expr<'tcx>, else_expr: &'tcx hir::Expr<'tcx>, then_ty: Ty<'tcx>, @@ -357,8 +358,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` if block.expr.is_none() && block.stmts.is_empty() && let Some(outer_span) = &mut outer_span + && let Some(cond_span) = cond_span.find_ancestor_inside(*outer_span) { - *outer_span = self.tcx.sess.source_map().guess_head_span(*outer_span); + *outer_span = outer_span.with_hi(cond_span.hi()) } (self.find_block_span(block), block.hir_id) diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 0836f15a122..75f5aced855 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -5,7 +5,7 @@ use crate::type_error_struct; use rustc_errors::{struct_span_err, Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def::{self, Namespace, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_infer::{ infer, traits::{self, Obligation}, @@ -19,11 +19,13 @@ use rustc_middle::ty::adjustment::{ }; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; +use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; + use std::iter; /// Checks that it is legal to call methods of the trait corresponding @@ -59,7 +61,7 @@ pub fn check_legal_trait_for_method_call( enum CallStep<'tcx> { Builtin(Ty<'tcx>), - DeferredClosure(DefId, ty::FnSig<'tcx>), + DeferredClosure(LocalDefId, ty::FnSig<'tcx>), /// E.g., enum variant constructors. Overloaded(MethodCallee<'tcx>), } @@ -145,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Closure(def_id, substs) => { - assert_eq!(def_id.krate, LOCAL_CRATE); + let def_id = def_id.expect_local(); // Check whether this is a call to a closure where we // haven't yet decided on whether the closure is fn vs @@ -558,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, arg_exprs: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, - closure_def_id: DefId, + closure_def_id: LocalDefId, fn_sig: ty::FnSig<'tcx>, ) -> Ty<'tcx> { // `fn_sig` is the *signature* of the closure being called. We @@ -581,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::TupleArguments, - Some(closure_def_id), + Some(closure_def_id.to_def_id()), ); fn_sig.output() diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 9497d5c4528..9c1fd9b30b4 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1098,7 +1098,7 @@ fn check_impl_items_against_trait<'tcx>( for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) { let is_implemented = ancestors .leaf_def(tcx, trait_item_id) - .map_or(false, |node_item| node_item.item.defaultness.has_value()); + .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value()); if !is_implemented && tcx.impl_defaultness(impl_id).is_final() { missing_items.push(tcx.associated_item(trait_item_id)); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index e3ac23686b6..666498403c4 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -165,7 +165,7 @@ fn compare_predicate_entailment<'tcx>( // Create mapping from trait to placeholder. let trait_to_placeholder_substs = - impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs); + impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs); debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs); let impl_m_generics = tcx.generics_of(impl_m.def_id); @@ -511,8 +511,8 @@ fn compare_self_type<'tcx>( let self_string = |method: &ty::AssocItem| { let untransformed_self_ty = match method.container { - ty::ImplContainer(_) => impl_trait_ref.self_ty(), - ty::TraitContainer(_) => tcx.types.self_param, + ty::ImplContainer => impl_trait_ref.self_ty(), + ty::TraitContainer => tcx.types.self_param, }; let self_arg_ty = tcx.fn_sig(method.def_id).input(0); let param_env = ty::ParamEnv::reveal_all(); @@ -1194,7 +1194,7 @@ fn compare_type_predicate_entailment<'tcx>( ) -> Result<(), ErrorGuaranteed> { let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); let trait_to_impl_substs = - impl_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); + impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs); let impl_ty_generics = tcx.generics_of(impl_ty.def_id); let trait_ty_generics = tcx.generics_of(trait_ty.def_id); @@ -1390,9 +1390,9 @@ pub fn check_type_bounds<'tcx>( }); let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); let impl_ty_substs = tcx.intern_substs(&substs); + let container_id = impl_ty.container_id(tcx); - let rebased_substs = - impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); + let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); let impl_ty_value = tcx.type_of(impl_ty.def_id); let param_env = tcx.param_env(impl_ty.def_id); @@ -1441,8 +1441,7 @@ pub fn check_type_bounds<'tcx>( debug!(?normalize_param_env); let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); - let rebased_substs = - impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); + let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); tcx.infer_ctxt().enter(move |infcx| { let ocx = ObligationCtxt::new(&infcx); @@ -1505,10 +1504,13 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let implied_bounds = match impl_ty.container { - ty::TraitContainer(_) => FxHashSet::default(), - ty::ImplContainer(def_id) => { - wfcheck::impl_implied_bounds(tcx, param_env, def_id.expect_local(), impl_ty_span) - } + ty::TraitContainer => FxHashSet::default(), + ty::ImplContainer => wfcheck::impl_implied_bounds( + tcx, + param_env, + container_id.expect_local(), + impl_ty_span, + ), }; let mut outlives_environment = OutlivesEnvironment::new(param_env); outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 58b0399c5c9..4de48dc5ba1 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -1,5 +1,6 @@ use crate::check::FnCtxt; use rustc_infer::infer::InferOk; +use rustc_middle::middle::stability::EvalResult; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::ObligationCause; @@ -363,18 +364,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let compatible_variants: Vec<(String, Option<String>)> = expected_adt + let compatible_variants: Vec<(String, _, _, Option<String>)> = expected_adt .variants() .iter() .filter(|variant| { - variant.fields.len() == 1 && variant.ctor_kind == hir::def::CtorKind::Fn + variant.fields.len() == 1 }) .filter_map(|variant| { let sole_field = &variant.fields[0]; let field_is_local = sole_field.did.is_local(); let field_is_accessible = - sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx); + sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx) + // Skip suggestions for unstable public fields (for example `Pin::pointer`) + && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked); if !field_is_local && !field_is_accessible { return None; @@ -391,33 +394,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(path) = variant_path.strip_prefix("std::prelude::") && let Some((_, path)) = path.split_once("::") { - return Some((path.to_string(), note_about_variant_field_privacy)); + return Some((path.to_string(), variant.ctor_kind, sole_field.name, note_about_variant_field_privacy)); } - Some((variant_path, note_about_variant_field_privacy)) + Some((variant_path, variant.ctor_kind, sole_field.name, note_about_variant_field_privacy)) } else { None } }) .collect(); - let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { - Some(ident) => format!("{ident}: "), - None => String::new(), + let suggestions_for = |variant: &_, ctor, field_name| { + let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!("{ident}: "), + None => String::new(), + }; + + let (open, close) = match ctor { + hir::def::CtorKind::Fn => ("(".to_owned(), ")"), + hir::def::CtorKind::Fictive => (format!(" {{ {field_name}: "), " }"), + + // unit variants don't have fields + hir::def::CtorKind::Const => unreachable!(), + }; + + vec![ + (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")), + (expr.span.shrink_to_hi(), close.to_owned()), + ] }; match &compatible_variants[..] { [] => { /* No variants to format */ } - [(variant, note)] => { + [(variant, ctor_kind, field_name, note)] => { // Just a single matching variant. err.multipart_suggestion_verbose( &format!( "try wrapping the expression in `{variant}`{note}", note = note.as_deref().unwrap_or("") ), - vec![ - (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), - (expr.span.shrink_to_hi(), ")".to_string()), - ], + suggestions_for(&**variant, *ctor_kind, *field_name), Applicability::MaybeIncorrect, ); } @@ -428,12 +443,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "try wrapping the expression in a variant of `{}`", self.tcx.def_path_str(expected_adt.did()) ), - compatible_variants.into_iter().map(|(variant, _)| { - vec![ - (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), - (expr.span.shrink_to_hi(), ")".to_string()), - ] - }), + compatible_variants.into_iter().map( + |(variant, ctor_kind, field_name, _)| { + suggestions_for(&variant, ctor_kind, field_name) + }, + ), Applicability::MaybeIncorrect, ); } @@ -761,7 +775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map( |did| { let ai = self.tcx.associated_item(did); - ai.container == ty::TraitContainer(clone_trait) + ai.trait_container(self.tcx) == Some(clone_trait) }, ), segment.ident.name, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index e20c6a2d99a..6e97b0bf2ab 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1003,8 +1003,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let else_diverges = self.diverges.get(); let opt_suggest_box_span = self.opt_suggest_box_span(else_ty, orig_expected); - let if_cause = - self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span); + let if_cause = self.if_cause( + sp, + cond_expr.span, + then_expr, + else_expr, + then_ty, + else_ty, + opt_suggest_box_span, + ); coerce.coerce(self, &if_cause, else_expr, else_ty); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index d1c10a3b63c..3a809334511 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -29,6 +29,7 @@ use rustc_middle::ty::{ ToPredicate, Ty, UserType, }; use rustc_session::lint; +use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, DUMMY_SP}; @@ -114,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn record_deferred_call_resolution( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, r: DeferredCallResolution<'tcx>, ) { let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); @@ -123,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn remove_deferred_call_resolutions( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, ) -> Vec<DeferredCallResolution<'tcx>> { let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default() @@ -1089,13 +1090,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_alias_variant_ctor = true; } Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => { - let container = tcx.associated_item(def_id).container; - debug!(?def_id, ?container); + let assoc_item = tcx.associated_item(def_id); + let container = assoc_item.container; + let container_id = assoc_item.container_id(tcx); + debug!(?def_id, ?container, ?container_id); match container { - ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(tcx, span, None, span, trait_did) + ty::TraitContainer => { + callee::check_legal_trait_for_method_call(tcx, span, None, span, container_id) } - ty::ImplContainer(impl_def_id) => { + ty::ImplContainer => { if segments.len() == 1 { // `<T>::assoc` will end up here, and so // can `T::assoc`. It this came from an @@ -1103,7 +1106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `T` for posterity (see `UserSelfTy` for // details). let self_ty = self_ty.expect("UFCS sugared assoc missing Self"); - user_self_ty = Some(UserSelfTy { impl_def_id, self_ty }); + user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty }); } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 097fff6418e..57771e0969b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -839,8 +839,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && results.type_dependent_def_id(expr.hir_id).map_or( false, |did| { - self.tcx.associated_item(did).container - == ty::AssocItemContainer::TraitContainer(clone_trait_did) + let assoc_item = self.tcx.associated_item(did); + assoc_item.container == ty::AssocItemContainer::TraitContainer + && assoc_item.container_id(self.tcx) == clone_trait_did }, ) // If that clone call hasn't already dereferenced the self type (i.e. don't give this diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 99895dc1224..cd152eb97f1 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -2,13 +2,14 @@ use super::callee::DeferredCallResolution; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_hir::def_id::{DefIdMap, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; use rustc_infer::infer; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::def_id::LocalDefIdMap; use rustc_span::{self, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; @@ -46,7 +47,7 @@ pub struct Inherited<'a, 'tcx> { // decision. We keep these deferred resolutions grouped by the // def-id of the closure, so that once we decide, we can easily go // back and process them. - pub(super) deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolution<'tcx>>>>, + pub(super) deferred_call_resolutions: RefCell<LocalDefIdMap<Vec<DeferredCallResolution<'tcx>>>>, pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>, diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index b14f3d6de4e..2c89b63ae84 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -238,7 +238,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) -> SubstsRef<'tcx> { match pick.kind { probe::InherentImplPick => { - let impl_def_id = pick.item.container.id(); + let impl_def_id = pick.item.container_id(self.tcx); assert!( self.tcx.impl_trait_ref(impl_def_id).is_none(), "impl {:?} is not an inherent impl", @@ -248,7 +248,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } probe::ObjectPick => { - let trait_def_id = pick.item.container.id(); + let trait_def_id = pick.item.container_id(self.tcx); self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { // The object data has no entry for the Self // Type. For the purposes of this method call, we @@ -273,7 +273,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } probe::TraitPick => { - let trait_def_id = pick.item.container.id(); + let trait_def_id = pick.item.container_id(self.tcx); // Make a trait reference `$0 : Trait<$1...$n>` // consisting entirely of type variables. Later on in @@ -540,15 +540,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { // Disallow calls to the method `drop` defined in the `Drop` trait. - match pick.item.container { - ty::TraitContainer(trait_def_id) => callee::check_legal_trait_for_method_call( + if let Some(trait_def_id) = pick.item.trait_container(self.tcx) { + callee::check_legal_trait_for_method_call( self.tcx, self.span, Some(self.self_expr.span), self.call_expr.span, trait_def_id, - ), - ty::ImplContainer(..) => {} + ) } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index c09f63f1e8f..0e678c41f8b 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::AllTraits, ) { // If we find a different result the caller probably forgot to import a trait. - Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], + Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container_id(self.tcx)], Err(Ambiguity(ref sources)) => sources .iter() .filter_map(|source| { diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index a2f1f5692c7..7c68d930405 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_name = self.trait_path_or_bare_name( span, call_expr.hir_id, - pick.item.container.id(), + pick.item.container_id(self.tcx), ); let mut lint = lint.build(&format!( @@ -261,8 +261,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| { // "type" refers to either a type or, more likely, a trait from which // the associated function or method is from. - let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id()); - let trait_generics = self.tcx.generics_of(pick.item.container.id()); + let container_id = pick.item.container_id(self.tcx); + let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id); + let trait_generics = self.tcx.generics_of(container_id); let trait_name = if trait_generics.params.len() <= trait_generics.has_self as usize { diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 8f5f3657fc9..efe15fec7cb 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -592,9 +592,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) { let is_accessible = if let Some(name) = self.method_name { let item = candidate.item; - let def_scope = - self.tcx.adjust_ident_and_get_scope(name, item.container.id(), self.body_id).1; - item.vis.is_accessible_from(def_scope, self.tcx) + let def_scope = self + .tcx + .adjust_ident_and_get_scope(name, item.container_id(self.tcx), self.body_id) + .1; + item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) } else { true }; @@ -1025,7 +1027,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_extension_candidates_for_all_traits(); let out_of_scope_traits = match self.pick_core() { - Some(Ok(p)) => vec![p.item.container.id()], + Some(Ok(p)) => vec![p.item.container_id(self.tcx)], //Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(), Some(Err(MethodError::Ambiguity(v))) => v .into_iter() @@ -1387,7 +1389,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.tcx.def_path_str(stable_pick.item.def_id), )); } - (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer(def_id)) => { + (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => { + let def_id = stable_pick.item.container_id(self.tcx); diag.span_suggestion( self.span, "use the fully qualified path to the associated const", @@ -1429,9 +1432,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(..) => CandidateSource::Impl(candidate.item.container.id()), + InherentImplCandidate(..) => { + CandidateSource::Impl(candidate.item.container_id(self.tcx)) + } ObjectCandidate | WhereClauseCandidate(_) => { - CandidateSource::Trait(candidate.item.container.id()) + CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { let _ = self @@ -1444,7 +1449,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // to that impl. CandidateSource::Impl(impl_data.impl_def_id) } - _ => CandidateSource::Trait(candidate.item.container.id()), + _ => CandidateSource::Trait(candidate.item.container_id(self.tcx)), } }), } @@ -1502,7 +1507,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); // Check whether the impl imposes obligations we have to worry about. - let impl_def_id = probe.item.container.id(); + let impl_def_id = probe.item.container_id(self.tcx); let impl_bounds = self.tcx.predicates_of(impl_def_id); let impl_bounds = impl_bounds.instantiate(self.tcx, substs); let traits::Normalized { value: impl_bounds, obligations: norm_obligations } = @@ -1653,12 +1658,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { probes: &[(&Candidate<'tcx>, ProbeResult)], ) -> Option<Pick<'tcx>> { // Do all probes correspond to the same trait? - let container = probes[0].0.item.container; - if let ty::ImplContainer(_) = container { - return None; - } - if probes[1..].iter().any(|&(p, _)| p.item.container != container) { - return None; + let container = probes[0].0.item.trait_container(self.tcx)?; + for (p, _) in &probes[1..] { + let p_container = p.item.trait_container(self.tcx)?; + if p_container != container { + return None; + } } // FIXME: check the return type here somehow. diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 56fcd9e0a89..c92b93cbc22 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1789,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We point at the method, but we just skip the rest of the check for arbitrary // self types and rely on the suggestion to `use` the trait from // `suggest_valid_traits`. - let did = Some(pick.item.container.id()); + let did = Some(pick.item.container_id(self.tcx)); let skip = skippable.contains(&did); if pick.autoderefs == 0 && !skip { err.span_label( @@ -1825,7 +1825,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { debug!("try_alt_rcvr: pick candidate {:?}", pick); - let did = Some(pick.item.container.id()); + let did = Some(pick.item.container_id(self.tcx)); // We don't want to suggest a container type when the missing // method is `.clone()` or `.deref()` otherwise we'd suggest // `Arc::new(foo).clone()`, which is far from what the user wants. @@ -1937,7 +1937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // We only want to suggest public or local traits (#45781). - item.vis.is_public() || info.def_id.is_local() + item.visibility(self.tcx).is_public() || info.def_id.is_local() }) .is_some() }) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index d72e215934a..dd8f943b985 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -35,7 +35,6 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::UpvarRegion; @@ -186,6 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } }; + let closure_def_id = closure_def_id.expect_local(); let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs { self.closure_kind(closure_substs).is_none().then_some(closure_substs) @@ -193,20 +193,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; - let local_def_id = closure_def_id.expect_local(); - - let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); - assert_eq!(body_owner_def_id.to_def_id(), closure_def_id); + assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id); let mut delegate = InferBorrowKind { fcx: self, - closure_def_id: local_def_id, + closure_def_id, capture_information: Default::default(), fake_reads: Default::default(), }; euv::ExprUseVisitor::new( &mut delegate, &self.infcx, - body_owner_def_id, + closure_def_id, self.param_env, &self.typeck_results.borrow(), ) @@ -224,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.compute_min_captures(closure_def_id, capture_information, span); - let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); + let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id); if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) { self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span); @@ -239,7 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { for var_hir_id in upvars.keys() { - let place = self.place_for_root_variable(local_def_id, *var_hir_id); + let place = self.place_for_root_variable(closure_def_id, *var_hir_id); debug!("seed place {:?}", place); @@ -333,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Returns a list of `Ty`s for each upvar. - fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> { + fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> { self.typeck_results .borrow() .closure_min_captures_flattened(closure_id) @@ -511,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ``` fn compute_min_captures( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, capture_information: InferredCaptureInformation<'tcx>, closure_span: Span, ) { @@ -730,7 +727,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// `disjoint_capture_drop_reorder` if needed. fn perform_2229_migration_anaysis( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, body_id: hir::BodyId, capture_clause: hir::CaptureBy, span: Span, @@ -746,8 +743,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (migration_string, migrated_variables_concat) = migration_suggestion_for_2229(self.tcx, &need_migrations); - let closure_hir_id = - self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id); let closure_head_span = self.tcx.def_span(closure_def_id); self.tcx.struct_span_lint_hir( lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, @@ -1058,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn compute_2229_migrations_for_drop( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, closure_span: Span, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, closure_clause: hir::CaptureBy, @@ -1066,7 +1062,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option<FxHashSet<UpvarMigrationInfo>> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); - if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { + if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) { debug!("does not have significant drop"); return None; } @@ -1160,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn compute_2229_migrations( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, closure_span: Span, closure_clause: hir::CaptureBy, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, @@ -1343,14 +1339,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// implements Drop which will be affected since `y` isn't completely captured. fn has_significant_drop_outside_of_captures( &self, - closure_def_id: DefId, + closure_def_id: LocalDefId, closure_span: Span, base_path_ty: Ty<'tcx>, captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { - let needs_drop = |ty: Ty<'tcx>| { - ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) - }; + let needs_drop = + |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)); let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); @@ -1360,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { drop_trait, ty, ty_params, - self.tcx.param_env(closure_def_id.expect_local()), + self.tcx.param_env(closure_def_id), ) .must_apply_modulo_regions() }; @@ -1518,13 +1513,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn should_log_capture_analysis(&self, closure_def_id: DefId) -> bool { - self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis) + fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool { + self.tcx.has_attr(closure_def_id.to_def_id(), sym::rustc_capture_analysis) } fn log_capture_analysis_first_pass( &self, - closure_def_id: rustc_hir::def_id::DefId, + closure_def_id: LocalDefId, capture_information: &InferredCaptureInformation<'tcx>, closure_span: Span, ) { @@ -1543,7 +1538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn log_closure_min_capture_info(&self, closure_def_id: DefId, closure_span: Span) { + fn log_closure_min_capture_info(&self, closure_def_id: LocalDefId, closure_span: Span) { if self.should_log_capture_analysis(closure_def_id) { if let Some(min_captures) = self.typeck_results.borrow().closure_min_captures.get(&closure_def_id) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index faab862cc3c..95f32711225 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -977,11 +977,14 @@ fn check_associated_item( let item = tcx.associated_item(item_id); let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer(_) => (FxHashSet::default(), tcx.types.self_param), - ty::ImplContainer(def_id) => ( - impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span), - tcx.type_of(def_id), - ), + ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param), + ty::ImplContainer => { + let def_id = item.container_id(tcx); + ( + impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span), + tcx.type_of(def_id), + ) + } }; match item.kind { @@ -1004,10 +1007,10 @@ fn check_associated_item( check_method_receiver(wfcx, hir_sig, item, self_ty); } ty::AssocKind::Type => { - if let ty::AssocItemContainer::TraitContainer(_) = item.container { + if let ty::AssocItemContainer::TraitContainer = item.container { check_associated_type_bounds(wfcx, item, span) } - if item.defaultness.has_value() { + if item.defaultness(tcx).has_value() { let ty = tcx.type_of(item.def_id); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index fa6053ac395..f549807c39c 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -8,7 +8,6 @@ use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; @@ -348,14 +347,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn eval_closure_size(&mut self) { - let mut res: FxHashMap<DefId, ClosureSizeProfileData<'tcx>> = Default::default(); - for (closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() { - let closure_hir_id = - self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let mut res: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>> = Default::default(); + for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() { + let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); let data = self.resolve(*data, &closure_hir_id); - res.insert(*closure_def_id, data); + res.insert(closure_def_id, data); } self.typeck_results.closure_size_eval = res; @@ -365,7 +363,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.fcx.typeck_results.borrow().closure_min_captures.len(), Default::default(), ); - for (closure_def_id, root_min_captures) in + for (&closure_def_id, root_min_captures) in self.fcx.typeck_results.borrow().closure_min_captures.iter() { let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher( @@ -377,7 +375,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { .iter() .map(|captured_place| { let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| { - self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()) + self.tcx().hir().local_def_id_to_hir_id(closure_def_id) }); self.resolve(captured_place.clone(), &locatable) @@ -385,7 +383,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { .collect(); root_var_map_wb.insert(*var_hir_id, min_list_wb); } - min_captures_wb.insert(*closure_def_id, root_var_map_wb); + min_captures_wb.insert(closure_def_id, root_var_map_wb); } self.typeck_results.closure_min_captures = min_captures_wb; @@ -393,21 +391,20 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_fake_reads_map(&mut self) { let mut resolved_closure_fake_reads: FxHashMap< - DefId, + LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>, > = Default::default(); - for (closure_def_id, fake_reads) in + for (&closure_def_id, fake_reads) in self.fcx.typeck_results.borrow().closure_fake_reads.iter() { let mut resolved_fake_reads = Vec::<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>::new(); for (place, cause, hir_id) in fake_reads.iter() { - let locatable = - self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); let resolved_fake_read = self.resolve(place.clone(), &locatable); resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id)); } - resolved_closure_fake_reads.insert(*closure_def_id, resolved_fake_reads); + resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads); } self.typeck_results.closure_fake_reads = resolved_closure_fake_reads; } diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 1e404fda035..c23cbd71723 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -94,14 +94,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { // We'll try to suggest constraining type parameters to fulfill the requirements of // their `Copy` implementation. - let mut generics = None; - if let ty::Adt(def, _substs) = self_type.kind() { - let self_def_id = def.did(); - if let Some(local) = self_def_id.as_local() { - let self_item = tcx.hir().expect_item(local); - generics = self_item.kind.generics(); - } - } let mut errors: BTreeMap<_, Vec<_>> = Default::default(); let mut bounds = vec![]; @@ -163,16 +155,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate), ); } - if let Some(generics) = generics { - suggest_constraining_type_params( - tcx, - generics, - &mut err, - bounds.iter().map(|(param, constraint, def_id)| { - (param.as_str(), constraint.as_str(), *def_id) - }), - ); - } + suggest_constraining_type_params( + tcx, + tcx.hir().get_generics(impl_did).expect("impls always have generics"), + &mut err, + bounds.iter().map(|(param, constraint, def_id)| { + (param.as_str(), constraint.as_str(), *def_id) + }), + ); err.emit(); } Err(CopyImplementationError::NotAnAdt) => { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 36111637a56..99996e80c9c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1234,7 +1234,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { match item { Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { - if !item.defaultness.has_value() { + if !tcx.impl_defaultness(item.id.def_id).has_value() { tcx.sess .struct_span_err( item.span, @@ -2433,7 +2433,7 @@ fn explicit_predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Generic // supertrait). if let ty::Projection(projection) = ty.kind() { projection.substs == trait_identity_substs - && tcx.associated_item(projection.item_def_id).container.id() == def_id + && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id } else { false } @@ -3264,7 +3264,7 @@ fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<S /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if let Some(impl_item) = tcx.opt_associated_item(def_id) - && let ty::AssocItemContainer::ImplContainer(_) = impl_item.container + && let ty::AssocItemContainer::ImplContainer = impl_item.container && let Some(trait_item) = impl_item.trait_item_def_id { return tcx diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 8801d0260bf..0d2b75d3328 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -3,7 +3,7 @@ use crate::astconv::AstConv; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -30,7 +30,7 @@ fn associated_type_bounds<'tcx>( // Associated types are implicitly sized unless a `?Sized` bound is found <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); - let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); + let trait_def_id = tcx.parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 9d7420acd26..74a5b6e42c3 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -468,7 +468,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.borrow_expr(discr, ty::ImmBorrow); } else { let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), _ => None, }; @@ -642,7 +642,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) { let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), _ => None, }; @@ -666,7 +666,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// let binding, and *not* a match arm or nested pat.) fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), _ => None, }; @@ -763,7 +763,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { debug!("walk_captures({:?})", closure_expr); let tcx = self.tcx(); - let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id).to_def_id(); + let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id); let upvars = tcx.upvars_mentioned(self.body_owner); // For purposes of this function, generator and closures are equivalent. diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 8c26c96816d..9fee1eaaec9 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -106,7 +106,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) let item = tcx.associated_item(def_id); match item.kind { ty::AssocKind::Type => { - if item.defaultness.has_value() { + if item.defaultness(tcx).has_value() { cgp::parameters_for(&tcx.type_of(def_id), true) } else { Vec::new() diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 257a9520eeb..3b779280eda 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; use rustc_span::Span; use super::explicit::ExplicitPredicatesMap; @@ -202,7 +202,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( debug!("Projection"); check_explicit_predicates( tcx, - tcx.associated_item(obj.item_def_id).container.id(), + tcx.parent(obj.item_def_id), obj.substs, required_predicates, explicit_map, diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 057e47bfdd1..a596592311a 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -306,7 +306,9 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, let eh_context = EHContext { // The return address points 1 byte past the call instruction, // which could be in the next IP range in LSDA range table. - ip: if ip_before_instr != 0 { ip } else { ip - 1 }, + // + // `ip = -1` has special meaning, so use wrapping sub to allow for that + ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, func_start: uw::_Unwind_GetRegionStart(context), get_text_start: &|| uw::_Unwind_GetTextRelBase(context), get_data_start: &|| uw::_Unwind_GetDataRelBase(context), diff --git a/library/std/src/error.rs b/library/std/src/error.rs index ff7b70c328d..722df119d22 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -260,20 +260,6 @@ pub trait Error: Debug + Display { TypeId::of::<Self>() } - /// Returns a stack backtrace, if available, of where this error occurred. - /// - /// This function allows inspecting the location, in code, of where an error - /// happened. The returned `Backtrace` contains information about the stack - /// trace of the OS thread of execution of where the error originated from. - /// - /// Note that not all errors contain a `Backtrace`. Also note that a - /// `Backtrace` may actually be empty. For more information consult the - /// `Backtrace` type itself. - #[unstable(feature = "backtrace", issue = "53487")] - fn backtrace(&self) -> Option<&Backtrace> { - None - } - /// ``` /// if let Err(e) = "xc".parse::<u32>() { /// // Print `e` itself, no need for description(). @@ -370,7 +356,7 @@ pub trait Error: Debug + Display { } #[unstable(feature = "error_generic_member_access", issue = "99301")] -impl Provider for dyn Error + 'static { +impl<'b> Provider for dyn Error + 'b { fn provide<'a>(&'a self, req: &mut Demand<'a>) { self.provide(req) } @@ -757,8 +743,8 @@ impl<'a, T: Error + ?Sized> Error for &'a T { Error::source(&**self) } - fn backtrace(&self) -> Option<&Backtrace> { - Error::backtrace(&**self) + fn provide<'b>(&'b self, req: &mut Demand<'b>) { + Error::provide(&**self, req); } } @@ -778,8 +764,8 @@ impl<T: Error + ?Sized> Error for Arc<T> { Error::source(&**self) } - fn backtrace(&self) -> Option<&Backtrace> { - Error::backtrace(&**self) + fn provide<'a>(&'a self, req: &mut Demand<'a>) { + Error::provide(&**self, req); } } @@ -871,6 +857,20 @@ impl Error for alloc::ffi::IntoStringError { } } +impl<'a> dyn Error + 'a { + /// Request a reference of type `T` as context about this error. + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> { + core::any::request_ref(self) + } + + /// Request a value of type `T` as context about this error. + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn request_value<T: 'static>(&'a self) -> Option<T> { + core::any::request_value(self) + } +} + // Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the inner type is the same as `T`. @@ -910,18 +910,6 @@ impl dyn Error + 'static { None } } - - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { - core::any::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value<T: 'static>(&self) -> Option<T> { - core::any::request_value(self) - } } impl dyn Error + 'static + Send { @@ -949,13 +937,13 @@ impl dyn Error + 'static + Send { /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "99301")] pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { - <dyn Error + 'static>::request_ref(self) + <dyn Error>::request_ref(self) } /// Request a value of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "99301")] pub fn request_value<T: 'static>(&self) -> Option<T> { - <dyn Error + 'static>::request_value(self) + <dyn Error>::request_value(self) } } @@ -984,13 +972,13 @@ impl dyn Error + 'static + Send + Sync { /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "99301")] pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { - <dyn Error + 'static>::request_ref(self) + <dyn Error>::request_ref(self) } /// Request a value of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "99301")] pub fn request_value<T: 'static>(&self) -> Option<T> { - <dyn Error + 'static>::request_value(self) + <dyn Error>::request_value(self) } } @@ -1467,8 +1455,11 @@ impl<E> Report<E> { /// ```rust /// #![feature(error_reporter)] /// #![feature(backtrace)] + /// #![feature(provide_any)] + /// #![feature(error_generic_member_access)] /// # use std::error::Error; /// # use std::fmt; + /// use std::any::Demand; /// use std::error::Report; /// use std::backtrace::Backtrace; /// @@ -1498,8 +1489,9 @@ impl<E> Report<E> { /// } /// /// impl Error for SuperErrorSideKick { - /// fn backtrace(&self) -> Option<&Backtrace> { - /// Some(&self.backtrace) + /// fn provide<'a>(&'a self, req: &mut Demand<'a>) { + /// req + /// .provide_ref::<Backtrace>(&self.backtrace); /// } /// } /// @@ -1552,11 +1544,11 @@ where fn backtrace(&self) -> Option<&Backtrace> { // have to grab the backtrace on the first error directly since that error may not be // 'static - let backtrace = self.error.backtrace(); + let backtrace = (&self.error as &dyn Error).request_ref(); let backtrace = backtrace.or_else(|| { self.error .source() - .map(|source| source.chain().find_map(|source| source.backtrace())) + .map(|source| source.chain().find_map(|source| source.request_ref())) .flatten() }); backtrace @@ -1618,11 +1610,11 @@ impl Report<Box<dyn Error>> { fn backtrace(&self) -> Option<&Backtrace> { // have to grab the backtrace on the first error directly since that error may not be // 'static - let backtrace = self.error.backtrace(); + let backtrace = self.error.request_ref(); let backtrace = backtrace.or_else(|| { self.error .source() - .map(|source| source.chain().find_map(|source| source.backtrace())) + .map(|source| source.chain().find_map(|source| source.request_ref())) .flatten() }); backtrace diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs index a2a35d96ec9..ee999bd65c3 100644 --- a/library/std/src/error/tests.rs +++ b/library/std/src/error/tests.rs @@ -1,5 +1,6 @@ use super::Error; use crate::fmt; +use core::any::Demand; #[derive(Debug, PartialEq)] struct A; @@ -198,8 +199,8 @@ where self.source.as_deref() } - fn backtrace(&self) -> Option<&Backtrace> { - self.backtrace.as_ref() + fn provide<'a>(&'a self, req: &mut Demand<'a>) { + self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt)); } } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d799776548a..c8e131b6ee1 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -184,6 +184,11 @@ pub struct DirEntry(fs_imp::DirEntry); #[stable(feature = "rust1", since = "1.0.0")] pub struct OpenOptions(fs_imp::OpenOptions); +/// Representation of the various timestamps on a file. +#[derive(Copy, Clone, Debug, Default)] +#[unstable(feature = "file_set_times", issue = "98245")] +pub struct FileTimes(fs_imp::FileTimes); + /// Representation of the various permissions on a file. /// /// This module only currently provides one bit of information, @@ -596,6 +601,58 @@ impl File { pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { self.inner.set_permissions(perm.0) } + + /// Changes the timestamps of the underlying file. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `futimens` function on Unix (falling back to + /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this + /// [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior + /// + /// # Errors + /// + /// This function will return an error if the user lacks permission to change timestamps on the + /// underlying file. It may also return an error in other os-specific unspecified cases. + /// + /// This function may return an error if the operating system lacks support to change one or + /// more of the timestamps set in the `FileTimes` structure. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(file_set_times)] + /// + /// fn main() -> std::io::Result<()> { + /// use std::fs::{self, File, FileTimes}; + /// + /// let src = fs::metadata("src")?; + /// let dest = File::options().write(true).open("dest")?; + /// let times = FileTimes::new() + /// .set_accessed(src.accessed()?) + /// .set_modified(src.modified()?); + /// dest.set_times(times)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "file_set_times", issue = "98245")] + #[doc(alias = "futimens")] + #[doc(alias = "futimes")] + #[doc(alias = "SetFileTime")] + pub fn set_times(&self, times: FileTimes) -> io::Result<()> { + self.inner.set_times(times.0) + } + + /// Changes the modification time of the underlying file. + /// + /// This is an alias for `set_times(FileTimes::new().set_modified(time))`. + #[unstable(feature = "file_set_times", issue = "98245")] + #[inline] + pub fn set_modified(&self, time: SystemTime) -> io::Result<()> { + self.set_times(FileTimes::new().set_modified(time)) + } } // In addition to the `impl`s here, `File` also has `impl`s for @@ -1252,6 +1309,30 @@ impl FromInner<fs_imp::FileAttr> for Metadata { } } +impl FileTimes { + /// Create a new `FileTimes` with no times set. + /// + /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps. + #[unstable(feature = "file_set_times", issue = "98245")] + pub fn new() -> Self { + Self::default() + } + + /// Set the last access time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + pub fn set_accessed(mut self, t: SystemTime) -> Self { + self.0.set_accessed(t.into_inner()); + self + } + + /// Set the last modified time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + pub fn set_modified(mut self, t: SystemTime) -> Self { + self.0.set_modified(t.into_inner()); + self + } +} + impl Permissions { /// Returns `true` if these permissions describe a readonly (unwritable) file. /// diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 81dd042425c..53fee952a7a 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -7,12 +7,12 @@ use crate::hash; use crate::io::{self, Write}; use crate::iter; use crate::mem; -use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr}; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::option; use crate::slice; use crate::sys::net::netc as c; use crate::sys_common::net::LookupHost; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{FromInner, IntoInner}; use crate::vec; /// An internet socket address, either IPv4 or IPv6. @@ -73,12 +73,11 @@ pub enum SocketAddr { /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// assert_eq!(socket.port(), 8080); /// ``` -#[derive(Copy)] +#[derive(Copy, Clone, Eq, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV4 { - // Do not assume that this struct is implemented as the underlying system representation. - // The memory layout is not part of the stable interface that std exposes. - inner: c::sockaddr_in, + ip: Ipv4Addr, + port: u16, } /// An IPv6 socket address. @@ -107,12 +106,13 @@ pub struct SocketAddrV4 { /// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); /// assert_eq!(socket.port(), 8080); /// ``` -#[derive(Copy)] +#[derive(Copy, Clone, Eq, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV6 { - // Do not assume that this struct is implemented as the underlying system representation. - // The memory layout is not part of the stable interface that std exposes. - inner: c::sockaddr_in6, + ip: Ipv6Addr, + port: u16, + flowinfo: u32, + scope_id: u32, } impl SocketAddr { @@ -131,7 +131,8 @@ impl SocketAddr { /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] #[must_use] - pub fn new(ip: IpAddr, port: u16) -> SocketAddr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn new(ip: IpAddr, port: u16) -> SocketAddr { match ip { IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), @@ -277,15 +278,9 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { - SocketAddrV4 { - inner: c::sockaddr_in { - sin_family: c::AF_INET as c::sa_family_t, - sin_port: htons(port), - sin_addr: ip.into_inner(), - ..unsafe { mem::zeroed() } - }, - } + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { ip, port } } /// Returns the IP address associated with this socket address. @@ -302,9 +297,7 @@ impl SocketAddrV4 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn ip(&self) -> &Ipv4Addr { - // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`. - // It is safe to cast from `&in_addr` to `&Ipv4Addr`. - unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) } + &self.ip } /// Changes the IP address associated with this socket address. @@ -320,7 +313,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: Ipv4Addr) { - self.inner.sin_addr = new_ip.into_inner() + self.ip = new_ip; } /// Returns the port number associated with this socket address. @@ -337,7 +330,7 @@ impl SocketAddrV4 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn port(&self) -> u16 { - ntohs(self.inner.sin_port) + self.port } /// Changes the port number associated with this socket address. @@ -353,7 +346,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin_port = htons(new_port); + self.port = new_port; } } @@ -376,17 +369,9 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { - SocketAddrV6 { - inner: c::sockaddr_in6 { - sin6_family: c::AF_INET6 as c::sa_family_t, - sin6_port: htons(port), - sin6_addr: *ip.as_inner(), - sin6_flowinfo: flowinfo, - sin6_scope_id: scope_id, - ..unsafe { mem::zeroed() } - }, - } + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { + SocketAddrV6 { ip, port, flowinfo, scope_id } } /// Returns the IP address associated with this socket address. @@ -403,7 +388,7 @@ impl SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn ip(&self) -> &Ipv6Addr { - unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) } + &self.ip } /// Changes the IP address associated with this socket address. @@ -419,7 +404,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: Ipv6Addr) { - self.inner.sin6_addr = *new_ip.as_inner() + self.ip = new_ip; } /// Returns the port number associated with this socket address. @@ -436,7 +421,7 @@ impl SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn port(&self) -> u16 { - ntohs(self.inner.sin6_port) + self.port } /// Changes the port number associated with this socket address. @@ -452,7 +437,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin6_port = htons(new_port); + self.port = new_port; } /// Returns the flow information associated with this address. @@ -479,7 +464,7 @@ impl SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn flowinfo(&self) -> u32 { - self.inner.sin6_flowinfo + self.flowinfo } /// Changes the flow information associated with this socket address. @@ -497,7 +482,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_flowinfo(&mut self, new_flowinfo: u32) { - self.inner.sin6_flowinfo = new_flowinfo; + self.flowinfo = new_flowinfo; } /// Returns the scope ID associated with this address. @@ -519,7 +504,7 @@ impl SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn scope_id(&self) -> u32 { - self.inner.sin6_scope_id + self.scope_id } /// Changes the scope ID associated with this socket address. @@ -537,19 +522,48 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_scope_id(&mut self, new_scope_id: u32) { - self.inner.sin6_scope_id = new_scope_id; + self.scope_id = new_scope_id; } } impl FromInner<c::sockaddr_in> for SocketAddrV4 { fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { - SocketAddrV4 { inner: addr } + SocketAddrV4 { ip: Ipv4Addr::from_inner(addr.sin_addr), port: u16::from_be(addr.sin_port) } } } impl FromInner<c::sockaddr_in6> for SocketAddrV6 { fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { - SocketAddrV6 { inner: addr } + SocketAddrV6 { + ip: Ipv6Addr::from_inner(addr.sin6_addr), + port: u16::from_be(addr.sin6_port), + flowinfo: addr.sin6_flowinfo, + scope_id: addr.sin6_scope_id, + } + } +} + +impl IntoInner<c::sockaddr_in> for SocketAddrV4 { + fn into_inner(self) -> c::sockaddr_in { + c::sockaddr_in { + sin_family: c::AF_INET as c::sa_family_t, + sin_port: self.port.to_be(), + sin_addr: self.ip.into_inner(), + ..unsafe { mem::zeroed() } + } + } +} + +impl IntoInner<c::sockaddr_in6> for SocketAddrV6 { + fn into_inner(self) -> c::sockaddr_in6 { + c::sockaddr_in6 { + sin6_family: c::AF_INET6 as c::sa_family_t, + sin6_port: self.port.to_be(), + sin6_addr: self.ip.into_inner(), + sin6_flowinfo: self.flowinfo, + sin6_scope_id: self.scope_id, + ..unsafe { mem::zeroed() } + } } } @@ -582,19 +596,6 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr { } } -impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr { - fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) { - match *self { - SocketAddr::V4(ref a) => { - (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) - } - SocketAddr::V6(ref a) => { - (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for SocketAddr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -688,40 +689,6 @@ impl fmt::Debug for SocketAddrV6 { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for SocketAddrV4 { - fn clone(&self) -> SocketAddrV4 { - *self - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for SocketAddrV6 { - fn clone(&self) -> SocketAddrV6 { - *self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for SocketAddrV4 { - fn eq(&self, other: &SocketAddrV4) -> bool { - self.inner.sin_port == other.inner.sin_port - && self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for SocketAddrV6 { - fn eq(&self, other: &SocketAddrV6) -> bool { - self.inner.sin6_port == other.inner.sin6_port - && self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr - && self.inner.sin6_flowinfo == other.inner.sin6_flowinfo - && self.inner.sin6_scope_id == other.inner.sin6_scope_id - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for SocketAddrV4 {} -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for SocketAddrV6 {} - #[stable(feature = "socketaddr_ordering", since = "1.45.0")] impl PartialOrd for SocketAddrV4 { fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> { @@ -753,19 +720,13 @@ impl Ord for SocketAddrV6 { #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for SocketAddrV4 { fn hash<H: hash::Hasher>(&self, s: &mut H) { - (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) + (self.port, self.ip).hash(s) } } #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for SocketAddrV6 { fn hash<H: hash::Hasher>(&self, s: &mut H) { - ( - self.inner.sin6_port, - &self.inner.sin6_addr.s6_addr, - self.inner.sin6_flowinfo, - self.inner.sin6_scope_id, - ) - .hash(s) + (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s) } } diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 438bae01b60..41ca9ba8425 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -4,20 +4,16 @@ mod tests; use crate::cmp::Ordering; use crate::fmt::{self, Write as FmtWrite}; -use crate::hash; use crate::io::Write as IoWrite; use crate::mem::transmute; use crate::sys::net::netc as c; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{FromInner, IntoInner}; /// An IP address, either IPv4 or IPv6. /// /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their /// respective documentation for more details. /// -/// The size of an `IpAddr` instance may vary depending on the target operating -/// system. -/// /// # Examples /// /// ``` @@ -50,9 +46,6 @@ pub enum IpAddr { /// /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. /// -/// The size of an `Ipv4Addr` struct may vary depending on the target operating -/// system. -/// /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 /// /// # Textual representation @@ -77,10 +70,10 @@ pub enum IpAddr { /// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal /// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex /// ``` -#[derive(Copy)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { - inner: c::in_addr, + octets: [u8; 4], } /// An IPv6 address. @@ -88,9 +81,6 @@ pub struct Ipv4Addr { /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. /// They are usually represented as eight 16-bit segments. /// -/// The size of an `Ipv6Addr` struct may vary depending on the target operating -/// system. -/// /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// /// # Embedding IPv4 Addresses @@ -162,10 +152,10 @@ pub struct Ipv4Addr { /// assert_eq!("::1".parse(), Ok(localhost)); /// assert_eq!(localhost.is_loopback(), true); /// ``` -#[derive(Copy)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { - inner: c::in6_addr, + octets: [u8; 16], } /// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. @@ -461,9 +451,7 @@ impl Ipv4Addr { #[must_use] #[inline] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { - // `s_addr` is stored as BE on all machine and the array is in BE order. - // So the native endian conversion method is used so that it's never swapped. - Ipv4Addr { inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) } } + Ipv4Addr { octets: [a, b, c, d] } } /// An IPv4 address with the address pointing to localhost: `127.0.0.1` @@ -523,8 +511,7 @@ impl Ipv4Addr { #[must_use] #[inline] pub const fn octets(&self) -> [u8; 4] { - // This returns the order we want because s_addr is stored in big-endian. - self.inner.s_addr.to_ne_bytes() + self.octets } /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). @@ -547,7 +534,7 @@ impl Ipv4Addr { #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { - self.inner.s_addr == 0 + u32::from_be_bytes(self.octets) == 0 } /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`). @@ -910,9 +897,7 @@ impl Ipv4Addr { #[inline] pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); - Ipv6Addr { - inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }, - } + Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] } } /// Converts this address to an [IPv4-mapped] [`IPv6` address]. @@ -937,9 +922,7 @@ impl Ipv4Addr { #[inline] pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); - Ipv6Addr { - inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }, - } + Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] } } } @@ -1034,22 +1017,6 @@ impl fmt::Debug for Ipv4Addr { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Ipv4Addr { - #[inline] - fn clone(&self) -> Ipv4Addr { - *self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Ipv4Addr { - #[inline] - fn eq(&self, other: &Ipv4Addr) -> bool { - self.inner.s_addr == other.inner.s_addr - } -} - #[stable(feature = "ip_cmp", since = "1.16.0")] impl PartialEq<Ipv4Addr> for IpAddr { #[inline] @@ -1073,21 +1040,6 @@ impl PartialEq<IpAddr> for Ipv4Addr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Ipv4Addr {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Ipv4Addr { - #[inline] - fn hash<H: hash::Hasher>(&self, s: &mut H) { - // NOTE: - // * hash in big endian order - // * in netbsd, `in_addr` has `repr(packed)`, we need to - // copy `s_addr` to avoid unsafe borrowing - { self.inner.s_addr }.hash(s) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv4Addr { #[inline] fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { @@ -1121,15 +1073,21 @@ impl PartialOrd<IpAddr> for Ipv4Addr { impl Ord for Ipv4Addr { #[inline] fn cmp(&self, other: &Ipv4Addr) -> Ordering { - // Compare as native endian - u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr)) + self.octets.cmp(&other.octets) } } impl IntoInner<c::in_addr> for Ipv4Addr { #[inline] fn into_inner(self) -> c::in_addr { - self.inner + // `s_addr` is stored as BE on all machines and the array is in BE order. + // So the native endian conversion method is used so that it's never swapped. + c::in_addr { s_addr: u32::from_ne_bytes(self.octets) } + } +} +impl FromInner<c::in_addr> for Ipv4Addr { + fn from_inner(addr: c::in_addr) -> Ipv4Addr { + Ipv4Addr { octets: addr.s_addr.to_ne_bytes() } } } @@ -1147,8 +1105,7 @@ impl From<Ipv4Addr> for u32 { /// ``` #[inline] fn from(ip: Ipv4Addr) -> u32 { - let ip = ip.octets(); - u32::from_be_bytes(ip) + u32::from_be_bytes(ip.octets) } } @@ -1166,7 +1123,7 @@ impl From<u32> for Ipv4Addr { /// ``` #[inline] fn from(ip: u32) -> Ipv4Addr { - Ipv4Addr::from(ip.to_be_bytes()) + Ipv4Addr { octets: ip.to_be_bytes() } } } @@ -1184,7 +1141,7 @@ impl From<[u8; 4]> for Ipv4Addr { /// ``` #[inline] fn from(octets: [u8; 4]) -> Ipv4Addr { - Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]) + Ipv4Addr { octets } } } @@ -1234,13 +1191,9 @@ impl Ipv6Addr { h.to_be(), ]; Ipv6Addr { - inner: c::in6_addr { - // All elements in `addr16` are big endian. - // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. - // rustc_allow_const_fn_unstable: the transmute could be written as stable const - // code, but that leads to worse code generation (#75085) - s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) }, - }, + // All elements in `addr16` are big endian. + // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. + octets: unsafe { transmute::<_, [u8; 16]>(addr16) }, } } @@ -1285,11 +1238,9 @@ impl Ipv6Addr { #[must_use] #[inline] pub const fn segments(&self) -> [u16; 8] { - // All elements in `s6_addr` must be big endian. + // All elements in `self.octets` must be big endian. // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. - // rustc_allow_const_fn_unstable: the transmute could be written as stable const code, but - // that leads to worse code generation (#75085) - let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) }; + let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) }; // We want native endian u16 [ u16::from_be(a), @@ -1748,7 +1699,7 @@ impl Ipv6Addr { #[must_use] #[inline] pub const fn octets(&self) -> [u8; 16] { - self.inner.s6_addr + self.octets } } @@ -1856,22 +1807,6 @@ impl fmt::Debug for Ipv6Addr { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Ipv6Addr { - #[inline] - fn clone(&self) -> Ipv6Addr { - *self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Ipv6Addr { - #[inline] - fn eq(&self, other: &Ipv6Addr) -> bool { - self.inner.s6_addr == other.inner.s6_addr - } -} - #[stable(feature = "ip_cmp", since = "1.16.0")] impl PartialEq<IpAddr> for Ipv6Addr { #[inline] @@ -1895,17 +1830,6 @@ impl PartialEq<Ipv6Addr> for IpAddr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Ipv6Addr {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Ipv6Addr { - #[inline] - fn hash<H: hash::Hasher>(&self, s: &mut H) { - self.inner.s6_addr.hash(s) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv6Addr { #[inline] fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { @@ -1943,16 +1867,15 @@ impl Ord for Ipv6Addr { } } -impl AsInner<c::in6_addr> for Ipv6Addr { - #[inline] - fn as_inner(&self) -> &c::in6_addr { - &self.inner +impl IntoInner<c::in6_addr> for Ipv6Addr { + fn into_inner(self) -> c::in6_addr { + c::in6_addr { s6_addr: self.octets } } } impl FromInner<c::in6_addr> for Ipv6Addr { #[inline] fn from_inner(addr: c::in6_addr) -> Ipv6Addr { - Ipv6Addr { inner: addr } + Ipv6Addr { octets: addr.s6_addr } } } @@ -1973,8 +1896,7 @@ impl From<Ipv6Addr> for u128 { /// ``` #[inline] fn from(ip: Ipv6Addr) -> u128 { - let ip = ip.octets(); - u128::from_be_bytes(ip) + u128::from_be_bytes(ip.octets) } } #[stable(feature = "i128", since = "1.26.0")] @@ -2025,8 +1947,7 @@ impl From<[u8; 16]> for Ipv6Addr { /// ``` #[inline] fn from(octets: [u8; 16]) -> Ipv6Addr { - let inner = c::in6_addr { s6_addr: octets }; - Ipv6Addr::from_inner(inner) + Ipv6Addr { octets } } } diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 7956c6a25e4..c29509331d7 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -944,3 +944,26 @@ fn ip_const() { const IS_IP_V6: bool = IP_ADDRESS.is_ipv6(); assert!(!IS_IP_V6); } + +#[test] +fn structural_match() { + // test that all IP types can be structurally matched upon + + const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST; + match IPV4 { + Ipv4Addr::LOCALHOST => {} + _ => unreachable!(), + } + + const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST; + match IPV6 { + Ipv6Addr::LOCALHOST => {} + _ => unreachable!(), + } + + const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); + match IP { + IpAddr::V4(Ipv4Addr::LOCALHOST) => {} + _ => unreachable!(), + } +} diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 9ed4a98f943..e7a40bdaf8e 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -69,15 +69,6 @@ pub enum Shutdown { Both, } -#[inline] -const fn htons(i: u16) -> u16 { - i.to_be() -} -#[inline] -const fn ntohs(i: u16) -> u16 { - u16::from_be(i) -} - fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T> where F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>, diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 1d899525081..4c4cd7d1d1d 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -538,6 +538,4 @@ pub mod netc { #[derive(Copy, Clone)] pub struct sockaddr {} - - pub type socklen_t = usize; } diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index faeda5a854d..1b98ef993b0 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -230,8 +230,8 @@ impl Socket { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { - let (addrp, len) = addr.into_inner(); - cvt(netc::connect(self.0.raw(), addrp, len)) + let (addr, len) = addr.into_inner(); + cvt(netc::connect(self.0.raw(), addr.as_ptr(), len)) }; self.set_nonblocking(false)?; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 71522865b7d..41405cbf657 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -20,7 +20,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; target_os = "watchos", ))] use crate::sys::weak::syscall; -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "android", target_os = "macos"))] use crate::sys::weak::weak; use libc::{c_int, mode_t}; @@ -313,6 +313,9 @@ pub struct FilePermissions { mode: mode_t, } +#[derive(Copy, Clone)] +pub struct FileTimes([libc::timespec; 2]); + #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { mode: mode_t, @@ -507,6 +510,48 @@ impl FilePermissions { } } +impl FileTimes { + pub fn set_accessed(&mut self, t: SystemTime) { + self.0[0] = t.t.to_timespec().expect("Invalid system time"); + } + + pub fn set_modified(&mut self, t: SystemTime) { + self.0[1] = t.t.to_timespec().expect("Invalid system time"); + } +} + +struct TimespecDebugAdapter<'a>(&'a libc::timespec); + +impl fmt::Debug for TimespecDebugAdapter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("timespec") + .field("tv_sec", &self.0.tv_sec) + .field("tv_nsec", &self.0.tv_nsec) + .finish() + } +} + +impl fmt::Debug for FileTimes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FileTimes") + .field("accessed", &TimespecDebugAdapter(&self.0[0])) + .field("modified", &TimespecDebugAdapter(&self.0[1])) + .finish() + } +} + +impl Default for FileTimes { + fn default() -> Self { + // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return + // an error in `set_times`. + #[cfg(target_os = "redox")] + let omit = libc::timespec { tv_sec: 0, tv_nsec: 0 }; + #[cfg(not(target_os = "redox"))] + let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }; + Self([omit; 2]) + } +} + impl FileType { pub fn is_dir(&self) -> bool { self.is(libc::S_IFDIR) @@ -1029,6 +1074,48 @@ impl File { cvt_r(|| unsafe { libc::fchmod(self.as_raw_fd(), perm.mode) })?; Ok(()) } + + pub fn set_times(&self, times: FileTimes) -> io::Result<()> { + cfg_if::cfg_if! { + if #[cfg(target_os = "redox")] { + // Redox doesn't appear to support `UTIME_OMIT`. + drop(times); + Err(io::const_io_error!( + io::ErrorKind::Unsupported, + "setting file times not supported", + )) + } else if #[cfg(any(target_os = "android", target_os = "macos"))] { + // futimens requires macOS 10.13, and Android API level 19 + cvt(unsafe { + weak!(fn futimens(c_int, *const libc::timespec) -> c_int); + match futimens.get() { + Some(futimens) => futimens(self.as_raw_fd(), times.0.as_ptr()), + #[cfg(target_os = "macos")] + None => { + fn ts_to_tv(ts: &libc::timespec) -> libc::timeval { + libc::timeval { + tv_sec: ts.tv_sec, + tv_usec: (ts.tv_nsec / 1000) as _ + } + } + let timevals = [ts_to_tv(×.0[0]), ts_to_tv(×.0[1])]; + libc::futimes(self.as_raw_fd(), timevals.as_ptr()) + } + // futimes requires even newer Android. + #[cfg(target_os = "android")] + None => return Err(io::const_io_error!( + io::ErrorKind::Unsupported, + "setting file times requires Android API level >= 19", + )), + } + })?; + Ok(()) + } else { + cvt(unsafe { libc::futimens(self.as_raw_fd(), times.0.as_ptr()) })?; + Ok(()) + } + } + } } impl DirBuilder { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index a1bbc2d87b6..462a45b01ab 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -139,8 +139,8 @@ impl Socket { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { - let (addrp, len) = addr.into_inner(); - cvt(libc::connect(self.as_raw_fd(), addrp, len)) + let (addr, len) = addr.into_inner(); + cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len)) }; self.set_nonblocking(false)?; diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index d1d2847cd33..0e1a6257ed7 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -17,6 +17,9 @@ pub struct DirEntry(!); #[derive(Clone, Debug)] pub struct OpenOptions {} +#[derive(Copy, Clone, Debug, Default)] +pub struct FileTimes {} + pub struct FilePermissions(!); pub struct FileType(!); @@ -86,6 +89,11 @@ impl fmt::Debug for FilePermissions { } } +impl FileTimes { + pub fn set_accessed(&mut self, _t: SystemTime) {} + pub fn set_modified(&mut self, _t: SystemTime) {} +} + impl FileType { pub fn is_dir(&self) -> bool { self.0 @@ -237,6 +245,10 @@ impl File { pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { self.0 } + + pub fn set_times(&self, _times: FileTimes) -> io::Result<()> { + self.0 + } } impl DirBuilder { diff --git a/library/std/src/sys/unsupported/net.rs b/library/std/src/sys/unsupported/net.rs index 360115d5033..a5204a08453 100644 --- a/library/std/src/sys/unsupported/net.rs +++ b/library/std/src/sys/unsupported/net.rs @@ -363,6 +363,4 @@ pub mod netc { #[derive(Copy, Clone)] pub struct sockaddr {} - - pub type socklen_t = usize; } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index cd6815bfc21..6614ae397b5 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -63,6 +63,12 @@ pub struct FilePermissions { readonly: bool, } +#[derive(Copy, Clone, Debug, Default)] +pub struct FileTimes { + accessed: Option<wasi::Timestamp>, + modified: Option<wasi::Timestamp>, +} + #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub struct FileType { bits: wasi::Filetype, @@ -112,6 +118,16 @@ impl FilePermissions { } } +impl FileTimes { + pub fn set_accessed(&mut self, t: SystemTime) { + self.accessed = Some(t.to_wasi_timestamp_or_panic()); + } + + pub fn set_modified(&mut self, t: SystemTime) { + self.modified = Some(t.to_wasi_timestamp_or_panic()); + } +} + impl FileType { pub fn is_dir(&self) -> bool { self.bits == wasi::FILETYPE_DIRECTORY @@ -459,6 +475,15 @@ impl File { unsupported() } + pub fn set_times(&self, times: FileTimes) -> io::Result<()> { + self.fd.filestat_set_times( + times.accessed.unwrap_or(0), + times.modified.unwrap_or(0), + times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM) + | times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM), + ) + } + pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> { read_link(&self.fd, file) } diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 937b1b850e7..590d268c380 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -524,6 +524,4 @@ pub mod netc { #[derive(Copy, Clone)] pub struct sockaddr {} - - pub type socklen_t = usize; } diff --git a/library/std/src/sys/wasi/time.rs b/library/std/src/sys/wasi/time.rs index 088585654b9..3d326e49106 100644 --- a/library/std/src/sys/wasi/time.rs +++ b/library/std/src/sys/wasi/time.rs @@ -47,6 +47,10 @@ impl SystemTime { SystemTime(Duration::from_nanos(ts)) } + pub fn to_wasi_timestamp_or_panic(&self) -> wasi::Timestamp { + self.0.as_nanos().try_into().expect("time does not fit in WASI timestamp") + } + pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index c7a42ef9a93..478068c73ba 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -4,6 +4,7 @@ #![cfg_attr(test, allow(dead_code))] #![unstable(issue = "none", feature = "windows_c")] +use crate::ffi::CStr; use crate::mem; use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort}; use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull}; @@ -619,7 +620,7 @@ pub struct SOCKADDR { } #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, Default)] pub struct FILETIME { pub dwLowDateTime: DWORD, pub dwHighDateTime: DWORD, @@ -887,6 +888,12 @@ extern "system" { pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; + pub fn SetFileTime( + hFile: BorrowedHandle<'_>, + lpCreationTime: Option<&FILETIME>, + lpLastAccessTime: Option<&FILETIME>, + lpLastWriteTime: Option<&FILETIME>, + ) -> BOOL; pub fn SetLastError(dwErrCode: DWORD); pub fn GetCommandLineW() -> LPWSTR; pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD; @@ -1219,8 +1226,8 @@ extern "system" { // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. -compat_fn! { - "kernel32": +compat_fn_with_fallback! { + pub static KERNEL32: &CStr = ansi_str!("kernel32"); // >= Win10 1607 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription @@ -1243,8 +1250,8 @@ compat_fn! { } } -compat_fn! { - "api-ms-win-core-synch-l1-2-0": +compat_fn_optional! { + pub static SYNCH_API: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); // >= Windows 8 / Server 2012 // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress @@ -1253,17 +1260,13 @@ compat_fn! { CompareAddress: LPVOID, AddressSize: SIZE_T, dwMilliseconds: DWORD - ) -> BOOL { - panic!("WaitOnAddress not available") - } - pub fn WakeByAddressSingle(Address: LPVOID) -> () { - // If this api is unavailable, there cannot be anything waiting, because - // WaitOnAddress would've panicked. So it's fine to do nothing here. - } + ) -> BOOL; + pub fn WakeByAddressSingle(Address: LPVOID) -> (); } -compat_fn! { - "ntdll": +compat_fn_with_fallback! { + pub static NTDLL: &CStr = ansi_str!("ntdll"); + pub fn NtCreateFile( FileHandle: *mut HANDLE, DesiredAccess: ACCESS_MASK, diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index ded97bb7eaa..ccc90177a20 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -49,81 +49,225 @@ //! * call any Rust function or CRT function that touches any static //! (global) state. -macro_rules! compat_fn { - ($module:literal: $( +use crate::ffi::{c_void, CStr}; +use crate::ptr::NonNull; +use crate::sys::c; + +/// Helper macro for creating CStrs from literals and symbol names. +macro_rules! ansi_str { + (sym $ident:ident) => {{ + #[allow(unused_unsafe)] + crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes()) + }}; + ($lit:literal) => {{ crate::sys::compat::const_cstr_from_bytes(concat!($lit, "\0").as_bytes()) }}; +} + +/// Creates a C string wrapper from a byte slice, in a constant context. +/// +/// This is a utility function used by the [`ansi_str`] macro. +/// +/// # Panics +/// +/// Panics if the slice is not null terminated or contains nulls, except as the last item +pub(crate) const fn const_cstr_from_bytes(bytes: &'static [u8]) -> &'static CStr { + if !matches!(bytes.last(), Some(&0)) { + panic!("A CStr must be null terminated"); + } + let mut i = 0; + // At this point `len()` is at least 1. + while i < bytes.len() - 1 { + if bytes[i] == 0 { + panic!("A CStr must not have interior nulls") + } + i += 1; + } + // SAFETY: The safety is ensured by the above checks. + unsafe { crate::ffi::CStr::from_bytes_with_nul_unchecked(bytes) } +} + +#[used] +#[link_section = ".CRT$XCU"] +static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init; + +/// This is where the magic preloading of symbols happens. +/// +/// Note that any functions included here will be unconditionally included in +/// the final binary, regardless of whether or not they're actually used. +/// +/// Therefore, this is limited to `compat_fn_optional` functions which must be +/// preloaded and any functions which may be more time sensitive, even for the first call. +unsafe extern "C" fn init() { + // There is no locking here. This code is executed before main() is entered, and + // is guaranteed to be single-threaded. + // + // DO NOT do anything interesting or complicated in this function! DO NOT call + // any Rust functions or CRT functions if those functions touch any global state, + // because this function runs during global initialization. For example, DO NOT + // do any dynamic allocation, don't call LoadLibrary, etc. + + if let Some(synch) = Module::new(c::SYNCH_API) { + // These are optional and so we must manually attempt to load them + // before they can be used. + c::WaitOnAddress::preload(synch); + c::WakeByAddressSingle::preload(synch); + } + + if let Some(kernel32) = Module::new(c::KERNEL32) { + // Preloading this means getting a precise time will be as fast as possible. + c::GetSystemTimePreciseAsFileTime::preload(kernel32); + } +} + +/// Represents a loaded module. +/// +/// Note that the modules std depends on must not be unloaded. +/// Therefore a `Module` is always valid for the lifetime of std. +#[derive(Copy, Clone)] +pub(in crate::sys) struct Module(NonNull<c_void>); +impl Module { + /// Try to get a handle to a loaded module. + /// + /// # SAFETY + /// + /// This should only be use for modules that exist for the lifetime of std + /// (e.g. kernel32 and ntdll). + pub unsafe fn new(name: &CStr) -> Option<Self> { + // SAFETY: A CStr is always null terminated. + let module = c::GetModuleHandleA(name.as_ptr()); + NonNull::new(module).map(Self) + } + + // Try to get the address of a function. + pub fn proc_address(self, name: &CStr) -> Option<NonNull<c_void>> { + // SAFETY: + // `self.0` will always be a valid module. + // A CStr is always null terminated. + let proc = unsafe { c::GetProcAddress(self.0.as_ptr(), name.as_ptr()) }; + NonNull::new(proc) + } +} + +/// Load a function or use a fallback implementation if that fails. +macro_rules! compat_fn_with_fallback { + (pub static $module:ident: &CStr = $name:expr; $( $(#[$meta:meta])* pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block - )*) => ($( + )*) => ( + pub static $module: &CStr = $name; + $( $(#[$meta])* pub mod $symbol { #[allow(unused_imports)] use super::*; use crate::mem; + use crate::ffi::CStr; + use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sys::compat::Module; type F = unsafe extern "system" fn($($argtype),*) -> $rettype; - /// Points to the DLL import, or the fallback function. - /// - /// This static can be an ordinary, unsynchronized, mutable static because - /// we guarantee that all of the writes finish during CRT initialization, - /// and all of the reads occur after CRT initialization. - static mut PTR: Option<F> = None; - - /// This symbol is what allows the CRT to find the `init` function and call it. - /// It is marked `#[used]` because otherwise Rust would assume that it was not - /// used, and would remove it. - #[used] - #[link_section = ".CRT$XCU"] - static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init; - - unsafe extern "C" fn init() { - PTR = get_f(); + /// `PTR` contains a function pointer to one of three functions. + /// It starts with the `load` function. + /// When that is called it attempts to load the requested symbol. + /// If it succeeds, `PTR` is set to the address of that symbol. + /// If it fails, then `PTR` is set to `fallback`. + static PTR: AtomicPtr<c_void> = AtomicPtr::new(load as *mut _); + + unsafe extern "system" fn load($($argname: $argtype),*) -> $rettype { + let func = load_from_module(Module::new($module)); + func($($argname),*) } - unsafe extern "C" fn get_f() -> Option<F> { - // There is no locking here. This code is executed before main() is entered, and - // is guaranteed to be single-threaded. - // - // DO NOT do anything interesting or complicated in this function! DO NOT call - // any Rust functions or CRT functions, if those functions touch any global state, - // because this function runs during global initialization. For example, DO NOT - // do any dynamic allocation, don't call LoadLibrary, etc. - let module_name: *const u8 = concat!($module, "\0").as_ptr(); - let symbol_name: *const u8 = concat!(stringify!($symbol), "\0").as_ptr(); - let module_handle = $crate::sys::c::GetModuleHandleA(module_name as *const i8); - if !module_handle.is_null() { - let ptr = $crate::sys::c::GetProcAddress(module_handle, symbol_name as *const i8); - if !ptr.is_null() { - // Transmute to the right function pointer type. - return Some(mem::transmute(ptr)); + fn load_from_module(module: Option<Module>) -> F { + unsafe { + static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol); + if let Some(f) = module.and_then(|m| m.proc_address(SYMBOL_NAME)) { + PTR.store(f.as_ptr(), Ordering::Relaxed); + mem::transmute(f) + } else { + PTR.store(fallback as *mut _, Ordering::Relaxed); + fallback } } - return None; } - #[allow(dead_code)] + #[allow(unused_variables)] + unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype { + $fallback_body + } + + #[allow(unused)] + pub(in crate::sys) fn preload(module: Module) { + load_from_module(Some(module)); + } + + #[inline(always)] + pub unsafe fn call($($argname: $argtype),*) -> $rettype { + let func: F = mem::transmute(PTR.load(Ordering::Relaxed)); + func($($argname),*) + } + } + $(#[$meta])* + pub use $symbol::call as $symbol; + )*) +} + +/// A function that either exists or doesn't. +/// +/// NOTE: Optional functions must be preloaded in the `init` function above, or they will always be None. +macro_rules! compat_fn_optional { + (pub static $module:ident: &CStr = $name:expr; $( + $(#[$meta:meta])* + pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty; + )*) => ( + pub static $module: &CStr = $name; + $( + $(#[$meta])* + pub mod $symbol { + #[allow(unused_imports)] + use super::*; + use crate::mem; + use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sys::compat::Module; + use crate::ptr::{self, NonNull}; + + type F = unsafe extern "system" fn($($argtype),*) -> $rettype; + + /// `PTR` will either be `null()` or set to the loaded function. + static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut()); + + /// Only allow access to the function if it has loaded successfully. #[inline(always)] + #[cfg(not(miri))] pub fn option() -> Option<F> { unsafe { - if cfg!(miri) { - // Miri does not run `init`, so we just call `get_f` each time. - get_f() - } else { - PTR - } + NonNull::new(PTR.load(Ordering::Relaxed)).map(|f| mem::transmute(f)) } } - #[allow(dead_code)] - pub unsafe fn call($($argname: $argtype),*) -> $rettype { - if let Some(ptr) = option() { - return ptr($($argname),*); + // Miri does not understand the way we do preloading + // therefore load the function here instead. + #[cfg(miri)] + pub fn option() -> Option<F> { + let mut func = NonNull::new(PTR.load(Ordering::Relaxed)); + if func.is_none() { + unsafe { Module::new($module).map(preload) }; + func = NonNull::new(PTR.load(Ordering::Relaxed)); + } + unsafe { + func.map(|f| mem::transmute(f)) } - $fallback_body } - } - $(#[$meta])* - pub use $symbol::call as $symbol; + #[allow(unused)] + pub(in crate::sys) fn preload(module: Module) { + unsafe { + static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol); + if let Some(f) = module.proc_address(SYMBOL_NAME) { + PTR.store(f.as_ptr(), Ordering::Relaxed); + } + } + } + } )*) } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index c96bcf41d51..aed082b3e0a 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -83,6 +83,12 @@ pub struct FilePermissions { attrs: c::DWORD, } +#[derive(Copy, Clone, Debug, Default)] +pub struct FileTimes { + accessed: Option<c::FILETIME>, + modified: Option<c::FILETIME>, +} + #[derive(Debug)] pub struct DirBuilder; @@ -536,6 +542,21 @@ impl File { })?; Ok(()) } + + pub fn set_times(&self, times: FileTimes) -> io::Result<()> { + let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0; + if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "Cannot set file timestamp to 0", + )); + } + cvt(unsafe { + c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref()) + })?; + Ok(()) + } + /// Get only basic file information such as attributes and file times. fn basic_info(&self) -> io::Result<c::FILE_BASIC_INFO> { unsafe { @@ -903,6 +924,16 @@ impl FilePermissions { } } +impl FileTimes { + pub fn set_accessed(&mut self, t: SystemTime) { + self.accessed = Some(t.into_inner()); + } + + pub fn set_modified(&mut self, t: SystemTime) { + self.modified = Some(t.into_inner()); + } +} + impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { FileType { attributes: attrs, reparse_tag } diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index d1e72cd5443..e0701a498fa 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -143,8 +143,8 @@ impl Socket { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let result = { - let (addrp, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw_socket(), addrp, len) }; + let (addr, len) = addr.into_inner(); + let result = unsafe { c::connect(self.as_raw_socket(), addr.as_ptr(), len) }; cvt(result).map(drop) }; self.set_nonblocking(false)?; diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs index 8f46781c753..b8209a85445 100644 --- a/library/std/src/sys/windows/time.rs +++ b/library/std/src/sys/windows/time.rs @@ -2,6 +2,7 @@ use crate::cmp::Ordering; use crate::fmt; use crate::mem; use crate::sys::c; +use crate::sys_common::IntoInner; use crate::time::Duration; use core::hash::{Hash, Hasher}; @@ -136,6 +137,12 @@ impl From<c::FILETIME> for SystemTime { } } +impl IntoInner<c::FILETIME> for SystemTime { + fn into_inner(self) -> c::FILETIME { + self.t + } +} + impl Hash for SystemTime { fn hash<H: Hasher>(&self, state: &mut H) { self.intervals().hash(state) diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index c13bda32823..33d336c4317 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -10,7 +10,7 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::ptr; use crate::sys::net::netc as c; use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket}; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{FromInner, IntoInner}; use crate::time::Duration; use libc::{c_int, c_void}; @@ -224,8 +224,8 @@ impl TcpStream { let sock = Socket::new(addr, c::SOCK_STREAM)?; - let (addrp, len) = addr.into_inner(); - cvt_r(|| unsafe { c::connect(sock.as_raw(), addrp, len) })?; + let (addr, len) = addr.into_inner(); + cvt_r(|| unsafe { c::connect(sock.as_raw(), addr.as_ptr(), len) })?; Ok(TcpStream { inner: sock }) } @@ -395,8 +395,8 @@ impl TcpListener { setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; // Bind our new socket - let (addrp, len) = addr.into_inner(); - cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?; + let (addr, len) = addr.into_inner(); + cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; cfg_if::cfg_if! { if #[cfg(target_os = "horizon")] { @@ -500,8 +500,8 @@ impl UdpSocket { init(); let sock = Socket::new(addr, c::SOCK_DGRAM)?; - let (addrp, len) = addr.into_inner(); - cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?; + let (addr, len) = addr.into_inner(); + cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; Ok(UdpSocket { inner: sock }) } @@ -531,14 +531,14 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> { let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; - let (dstp, dstlen) = dst.into_inner(); + let (dst, dstlen) = dst.into_inner(); let ret = cvt(unsafe { c::sendto( self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL, - dstp, + dst.as_ptr(), dstlen, ) })?; @@ -621,7 +621,7 @@ impl UdpSocket { pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_multiaddr: multiaddr.into_inner(), ipv6mr_interface: to_ipv6mr_interface(interface), }; setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) @@ -637,7 +637,7 @@ impl UdpSocket { pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_multiaddr: multiaddr.into_inner(), ipv6mr_interface: to_ipv6mr_interface(interface), }; setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) @@ -677,8 +677,8 @@ impl UdpSocket { } pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { - let (addrp, len) = addr?.into_inner(); - cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addrp, len) }).map(drop) + let (addr, len) = addr?.into_inner(); + cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop) } } @@ -700,3 +700,38 @@ impl fmt::Debug for UdpSocket { res.field(name, &self.inner.as_raw()).finish() } } + +//////////////////////////////////////////////////////////////////////////////// +// Converting SocketAddr to libc representation +//////////////////////////////////////////////////////////////////////////////// + +/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level +/// SocketAddr* types into their system representation. The benefit of this specific +/// type over using `c::sockaddr_storage` is that this type is exactly as large as it +/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust. +#[repr(C)] +pub(crate) union SocketAddrCRepr { + v4: c::sockaddr_in, + v6: c::sockaddr_in6, +} + +impl SocketAddrCRepr { + pub fn as_ptr(&self) -> *const c::sockaddr { + self as *const _ as *const c::sockaddr + } +} + +impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr { + fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) { + match *self { + SocketAddr::V4(ref a) => { + let sockaddr = SocketAddrCRepr { v4: a.into_inner() }; + (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t) + } + SocketAddr::V6(ref a) => { + let sockaddr = SocketAddrCRepr { v6: a.into_inner() }; + (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t) + } + } + } +} diff --git a/library/std/src/time.rs b/library/std/src/time.rs index b2014f462bd..759a59e1f98 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -38,7 +38,7 @@ use crate::error::Error; use crate::fmt; use crate::ops::{Add, AddAssign, Sub, SubAssign}; use crate::sys::time; -use crate::sys_common::FromInner; +use crate::sys_common::{FromInner, IntoInner}; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; @@ -686,3 +686,9 @@ impl FromInner<time::SystemTime> for SystemTime { SystemTime(time) } } + +impl IntoInner<time::SystemTime> for SystemTime { + fn into_inner(self) -> time::SystemTime { + self.0 + } +} diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 394bd8b4e28..4e1e8ef9dea 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -140,7 +140,13 @@ impl Step for Std { cargo_subcommand(builder.kind), ); - cargo.arg("--all-targets"); + // If we're not in stage 0, tests and examples will fail to compile + // from `core` definitions being loaded from two different `libcore` + // .rmeta and .rlib files. + if compiler.stage == 0 { + cargo.arg("--all-targets"); + } + std_cargo(builder, target, compiler.stage, &mut cargo); // Explicitly pass -p for all dependencies krates -- this will force cargo diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 839a6d27199..06fa5039fdf 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -158,34 +158,38 @@ impl Step for ToolBuild { a transitive dependency has different features activated \ than in a previous build:\n" ); - eprintln!( - "the following dependencies are duplicated although they \ - have the same features enabled:" - ); let (same, different): (Vec<_>, Vec<_>) = duplicates.into_iter().partition(|(_, cur, prev)| cur.2 == prev.2); - for (id, cur, prev) in same { - eprintln!(" {}", id); - // same features - eprintln!(" `{}` ({:?})\n `{}` ({:?})", cur.0, cur.1, prev.0, prev.1); - } - eprintln!("the following dependencies have different features:"); - for (id, cur, prev) in different { - eprintln!(" {}", id); - let cur_features: HashSet<_> = cur.2.into_iter().collect(); - let prev_features: HashSet<_> = prev.2.into_iter().collect(); - eprintln!( - " `{}` additionally enabled features {:?} at {:?}", - cur.0, - &cur_features - &prev_features, - cur.1 - ); + if !same.is_empty() { eprintln!( - " `{}` additionally enabled features {:?} at {:?}", - prev.0, - &prev_features - &cur_features, - prev.1 + "the following dependencies are duplicated although they \ + have the same features enabled:" ); + for (id, cur, prev) in same { + eprintln!(" {}", id); + // same features + eprintln!(" `{}` ({:?})\n `{}` ({:?})", cur.0, cur.1, prev.0, prev.1); + } + } + if !different.is_empty() { + eprintln!("the following dependencies have different features:"); + for (id, cur, prev) in different { + eprintln!(" {}", id); + let cur_features: HashSet<_> = cur.2.into_iter().collect(); + let prev_features: HashSet<_> = prev.2.into_iter().collect(); + eprintln!( + " `{}` additionally enabled features {:?} at {:?}", + cur.0, + &cur_features - &prev_features, + cur.1 + ); + eprintln!( + " `{}` additionally enabled features {:?} at {:?}", + prev.0, + &prev_features - &cur_features, + prev.1 + ); + } } eprintln!(); eprintln!( diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile new file mode 100644 index 00000000000..c2f3a16d273 --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12-stage1/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-12-tools \ + llvm-12-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-12 \ + --enable-llvm-link-shared \ + --set rust.thin-lto-import-instr-limit=10 + +ENV SCRIPT python2.7 ../x.py --stage 1 test --exclude src/tools/tidy && \ + # Run the `mir-opt` tests again but this time for a 32-bit target. + # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have + # both 32-bit and 64-bit outputs updated by the PR author, before + # the PR is approved and tested for merging. + # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, + # despite having different output on 32-bit vs 64-bit targets. + python2.7 ../x.py --stage 1 test src/test/mir-opt \ + --host='' --target=i686-unknown-linux-gnu \ No newline at end of file diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index f92e46b0a97..3ad4e3f97a3 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -134,7 +134,7 @@ x--expand-yaml-anchors--remove: uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" - if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' + if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf' <<: *step - name: collect CPU statistics @@ -286,7 +286,7 @@ jobs: - name: x86_64-gnu-llvm-12 <<: *job-linux-xl - + - name: x86_64-gnu-tools env: CI_ONLY_WHEN_SUBMODULES_CHANGED: 1 @@ -436,6 +436,11 @@ jobs: RUST_BACKTRACE: 1 <<: *job-linux-xl + - name: x86_64-gnu-llvm-12-stage1 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-xl + - name: x86_64-gnu-nopt <<: *job-linux-xl diff --git a/src/ci/run.sh b/src/ci/run.sh index 16d8bdb8153..6545475d996 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -43,7 +43,7 @@ else PYTHON="python2" fi -if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try; then +if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" fi diff --git a/src/ci/scripts/verify-channel.sh b/src/ci/scripts/verify-channel.sh index d02dc362c63..cd28748a44b 100755 --- a/src/ci/scripts/verify-channel.sh +++ b/src/ci/scripts/verify-channel.sh @@ -8,7 +8,7 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if isCiBranch auto || isCiBranch try; then +if isCiBranch auto || isCiBranch try || isCiBranch try-perf; then echo "channel verification is only executed on PR builds" exit fi diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject 766979590da8100998f0d662499d4a901d8d164 +Subproject befe6840874311635c417cf731377f07234ee37 diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1 index ff41324ef26..534af3f85bb 100644 --- a/src/doc/man/rustc.1 +++ b/src/doc/man/rustc.1 @@ -44,18 +44,18 @@ The optional \fIKIND\fR can be one of \fIstatic\fR, \fIdylib\fR, or \fIframework\fR. If omitted, \fIdylib\fR is assumed. .TP -\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|cdylib|staticlib] +\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|cdylib|staticlib|proc\-macro] Comma separated list of types of crates for the compiler to emit. .TP \fB\-\-crate\-name\fR \fINAME\fR Specify the name of the crate being built. .TP -\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info|mir][=\fIPATH\fR] +\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|metadata|link|dep\-info|mir][=\fIPATH\fR] Configure the output that \fBrustc\fR will produce. Each emission may also have an optional explicit output \fIPATH\fR specified for that particular emission kind. This path takes precedence over the \fB-o\fR option. .TP -\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs] +\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:target\-libdir|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs|\:stack\-protector\-strategies|\:link\-args] Comma separated list of compiler information to print on stdout. .TP \fB\-g\fR diff --git a/src/doc/reference b/src/doc/reference -Subproject a92be0fef439b3d8e0468d82cb24812d303520a +Subproject f3d3953bf3b158d596c96d55ce5366f9f3f972e diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 3155db49b0d57cd82c65456ac210b69ecec5ccb +Subproject ee342dc91e1ba1bb1e1f1318f84bbe3bfac0479 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject d5201cddace979b299ec1bf9fd8997338151aa9 +Subproject 04f3cf0bb2f5a6ee2bfc4b1a6a6cd8c11d1c553 diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 486b3d4414f..bfa92e7d32a 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -18,6 +18,9 @@ check cfg specification is parsed using the Rust metadata syntax, just as the `- These two options are independent. `names` checks only the namespace of condition names while `values` checks only the namespace of the values of list-valued conditions. +NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to +pass all expected names and values using `names(...)` and `values(...)`. + ## The `names(...)` form The `names(...)` form enables checking the names. This form uses a named list: @@ -53,27 +56,6 @@ The first form enables checking condition names, while specifying that there are condition names (outside of the set of well-known names defined by `rustc`). Omitting the `--check-cfg 'names(...)'` option does not enable checking condition names. -Conditions that are enabled are implicitly valid; it is unnecessary (but legal) to specify a -condition name as both enabled and valid. For example, the following invocations are equivalent: - -```bash -# condition names will be checked, and 'has_time_travel' is valid -rustc --cfg 'has_time_travel' --check-cfg 'names()' - -# condition names will be checked, and 'has_time_travel' is valid -rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)' -``` - -In contrast, the following two invocations are _not_ equivalent: - -```bash -# condition names will not be checked (because there is no --check-cfg names(...)) -rustc --cfg 'has_time_travel' - -# condition names will be checked, and 'has_time_travel' is both valid and enabled. -rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)' -``` - ## The `values(...)` form The `values(...)` form enables checking the values within list-valued conditions. It has this @@ -149,7 +131,7 @@ fn tame_lion() {} ```bash # This turns on checking for condition names, but not values, such as 'feature' values. rustc --check-cfg 'names(is_embedded, has_feathers)' \ - --cfg has_feathers --cfg 'feature = "zapping"' -Z unstable-options + --cfg has_feathers -Z unstable-options ``` ```rust @@ -159,13 +141,14 @@ fn do_embedded() {} #[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names() fn do_features() {} +#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names() + // and because no value checking was enable for "has_feathers" + // no warning is emited for the value "zapping" +fn do_zapping() {} + #[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and // "has_mumble_frotz" was not provided in names() fn do_mumble_frotz() {} - -#[cfg(feature = "lasers")] // This doesn't raise a warning, because values checking for "feature" - // was never used -fn shoot_lasers() {} ``` ### Example: Checking feature values, but not condition names diff --git a/src/doc/unstable-book/src/compiler-flags/location-detail.md b/src/doc/unstable-book/src/compiler-flags/location-detail.md index 08d937cc282..db070619969 100644 --- a/src/doc/unstable-book/src/compiler-flags/location-detail.md +++ b/src/doc/unstable-book/src/compiler-flags/location-detail.md @@ -17,8 +17,9 @@ within this list are: - `line` - the source line of the panic will be included in the panic output - `column` - the source column of the panic will be included in the panic output -Any combination of these three options are supported. If this option is not specified, -all three are included by default. +Any combination of these three options are supported. Alternatively, you can pass +`none` to this option, which results in no location details being tracked. +If this option is not specified, all three are included by default. An example of a panic output when using `-Z location-detail=line`: ```text diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 838283e32da..6577315a2b7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -439,7 +439,7 @@ pub(crate) fn build_impl( .unwrap(); // corresponding associated item has to exist !tcx.is_doc_hidden(trait_item.def_id) } else { - item.vis.is_public() + item.visibility(tcx).is_public() } }) .map(|item| item.clean(cx)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4067cf8441b..b6791bfab4a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1019,7 +1019,7 @@ impl<'tcx> Clean<'tcx, bool> for hir::IsAuto { impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> { fn clean(&self, cx: &mut DocContext<'tcx>) -> Path { - let path = self.path.clean(cx); + let path = clean_path(self.path, cx); register_res(cx, path.res); path } @@ -1101,7 +1101,7 @@ impl<'tcx> Clean<'tcx, Item> for hir::ImplItem<'tcx> { } hir::ImplItemKind::Fn(ref sig, body) => { let m = clean_function(cx, sig, self.generics, body); - let defaultness = cx.tcx.associated_item(self.def_id).defaultness; + let defaultness = cx.tcx.impl_defaultness(self.def_id); MethodItem(m, Some(defaultness)) } hir::ImplItemKind::TyAlias(hir_ty) => { @@ -1139,8 +1139,8 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { let ty = clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id)); let provided = match self.container { - ty::ImplContainer(_) => true, - ty::TraitContainer(_) => self.defaultness.has_value(), + ty::ImplContainer => true, + ty::TraitContainer => tcx.impl_defaultness(self.def_id).has_value(), }; if provided { AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id }) @@ -1159,8 +1159,8 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { if self.fn_has_self_parameter { let self_ty = match self.container { - ty::ImplContainer(def_id) => tcx.type_of(def_id), - ty::TraitContainer(_) => tcx.types.self_param, + ty::ImplContainer => tcx.type_of(self.container_id(tcx)), + ty::TraitContainer => tcx.types.self_param, }; let self_arg_ty = sig.input(0).skip_binder(); if self_arg_ty == self_ty { @@ -1178,13 +1178,13 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { } let provided = match self.container { - ty::ImplContainer(_) => true, - ty::TraitContainer(_) => self.defaultness.has_value(), + ty::ImplContainer => true, + ty::TraitContainer => self.defaultness(tcx).has_value(), }; if provided { let defaultness = match self.container { - ty::ImplContainer(_) => Some(self.defaultness), - ty::TraitContainer(_) => None, + ty::ImplContainer => Some(self.defaultness(tcx)), + ty::TraitContainer => None, }; MethodItem(Box::new(Function { generics, decl }), defaultness) } else { @@ -1215,7 +1215,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { } } - if let ty::TraitContainer(_) = self.container { + if let ty::TraitContainer = self.container { let bounds = tcx.explicit_item_bounds(self.def_id); let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; let mut generics = @@ -1232,7 +1232,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { if assoc.name != my_name { return false; } - if trait_.def_id() != self.container.id() { + if trait_.def_id() != self.container_id(tcx) { return false; } match **self_type { @@ -1280,7 +1280,7 @@ impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { None => bounds.push(GenericBound::maybe_sized(cx)), } - if self.defaultness.has_value() { + if tcx.impl_defaultness(self.def_id).has_value() { AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( @@ -1344,7 +1344,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type if let Some(expanded) = maybe_expand_private_type_alias(cx, path) { expanded } else { - let path = path.clean(cx); + let path = clean_path(path, cx); resolve_type(cx, path) } } @@ -1356,7 +1356,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type } let trait_segments = &p.segments[..p.segments.len() - 1]; - let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); + let trait_def = cx.tcx.associated_item(p.res.def_id()).container_id(cx.tcx); let trait_ = self::Path { res: Res::Def(DefKind::Trait, trait_def), segments: trait_segments.iter().map(|x| x.clean(cx)).collect(), @@ -1380,7 +1380,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type ty::Error(_) => return Type::Infer, _ => bug!("clean: expected associated type, found `{:?}`", ty), }; - let trait_ = hir::Path { span, res, segments: &[] }.clean(cx); + let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx); register_res(cx, trait_.res); let self_def_id = res.opt_def_id(); let self_type = clean_ty(qself, cx); @@ -1857,10 +1857,8 @@ fn clean_variant_data<'tcx>( } } -impl<'tcx> Clean<'tcx, Path> for hir::Path<'tcx> { - fn clean(&self, cx: &mut DocContext<'tcx>) -> Path { - Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() } - } +fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { + Path { res: path.res, segments: path.segments.iter().map(|x| x.clean(cx)).collect() } } impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> { @@ -1886,7 +1884,8 @@ impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> { }) .collect::<Vec<_>>() .into(); - let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect::<Vec<_>>().into(); + let bindings = + self.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<Vec<_>>().into(); GenericArgs::AngleBracketed { args, bindings } } } @@ -2172,7 +2171,7 @@ fn clean_use_statement<'tcx>( // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ - let path = path.clean(cx); + let path = clean_path(path, cx); let inner = if kind == hir::UseKind::Glob { if !denied { let mut visited = FxHashSet::default(); @@ -2252,24 +2251,19 @@ fn clean_maybe_renamed_foreign_item<'tcx>( }) } -impl<'tcx> Clean<'tcx, TypeBinding> for hir::TypeBinding<'tcx> { - fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBinding { - TypeBinding { - assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) }, - kind: self.kind.clean(cx), - } - } -} - -impl<'tcx> Clean<'tcx, TypeBindingKind> for hir::TypeBindingKind<'tcx> { - fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBindingKind { - match *self { +fn clean_type_binding<'tcx>( + type_binding: &hir::TypeBinding<'tcx>, + cx: &mut DocContext<'tcx>, +) -> TypeBinding { + TypeBinding { + assoc: PathSegment { name: type_binding.ident.name, args: type_binding.gen_args.clean(cx) }, + kind: match type_binding.kind { hir::TypeBindingKind::Equality { ref term } => { TypeBindingKind::Equality { term: clean_hir_term(term, cx) } } hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint { bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(), }, - } + }, } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d022ce9696a..1a46d077f1b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -122,10 +122,6 @@ pub(crate) struct Crate { pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>, } -// `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Crate, 72); - impl Crate { pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol { ExternalCrate::LOCAL.name(tcx) @@ -389,10 +385,6 @@ impl fmt::Debug for Item { } } -// `Item` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Item, 56); - pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { Span::new(def_id.as_local().map_or_else( || tcx.def_span(def_id), @@ -771,10 +763,6 @@ pub(crate) enum ItemKind { KeywordItem, } -// `ItemKind` is an enum and large variants can bloat up memory usage even for smaller ones -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ItemKind, 112); - impl ItemKind { /// Some items contain others such as structs (for their fields) and Enums /// (for their variants). This method returns those contained items. @@ -994,10 +982,6 @@ pub(crate) struct DocFragment { pub(crate) indent: usize, } -// `DocFragment` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(DocFragment, 32); - #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub(crate) enum DocFragmentKind { /// A doc fragment created from a `///` or `//!` doc comment. @@ -1382,10 +1366,6 @@ pub(crate) struct GenericParamDef { pub(crate) kind: GenericParamDefKind, } -// `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(GenericParamDef, 56); - impl GenericParamDef { pub(crate) fn is_synthetic_type_param(&self) -> bool { match self.kind { @@ -1590,10 +1570,6 @@ pub(crate) enum Type { ImplTrait(Vec<GenericBound>), } -// `Type` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Type, 72); - impl Type { /// When comparing types for equality, it can help to ignore `&` wrapping. pub(crate) fn without_borrowed_ref(&self) -> &Type { @@ -2230,33 +2206,18 @@ pub(crate) enum GenericArg { Infer, } -// `GenericArg` can occur many times in a single `Path`, so make sure it -// doesn't increase in size unexpectedly. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(GenericArg, 80); - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericArgs { AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> }, Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> }, } -// `GenericArgs` is in every `PathSegment`, so its size can significantly -// affect rustdoc's memory usage. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(GenericArgs, 32); - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct PathSegment { pub(crate) name: Symbol, pub(crate) args: GenericArgs, } -// `PathSegment` usually occurs multiple times in every `Path`, so its size can -// significantly affect rustdoc's memory usage. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(PathSegment, 40); - #[derive(Clone, Debug)] pub(crate) struct Typedef { pub(crate) type_: Type, @@ -2527,3 +2488,19 @@ impl SubstParam { if let Self::Lifetime(lt) = self { Some(lt) } else { None } } } + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // These are in alphabetical order, which is easy to maintain. + rustc_data_structures::static_assert_size!(Crate, 72); // frequently moved by-value + rustc_data_structures::static_assert_size!(DocFragment, 32); + rustc_data_structures::static_assert_size!(GenericArg, 80); + rustc_data_structures::static_assert_size!(GenericArgs, 32); + rustc_data_structures::static_assert_size!(GenericParamDef, 56); + rustc_data_structures::static_assert_size!(Item, 56); + rustc_data_structures::static_assert_size!(ItemKind, 112); + rustc_data_structures::static_assert_size!(PathSegment, 40); + rustc_data_structures::static_assert_size!(Type, 72); +} diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index d2ef89078bf..05547ea1515 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -213,7 +213,7 @@ impl<'a> Iterator for TokenIter<'a> { return None; } let token = rustc_lexer::first_token(self.src); - let (text, rest) = self.src.split_at(token.len); + let (text, rest) = self.src.split_at(token.len as usize); self.src = rest; Some((token.kind, text)) } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index aecc9aa879a..83fe14550cc 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1111,7 +1111,14 @@ table, } .item-info .stab { - display: inline-block; + width: fit-content; + /* This min-height is needed to unify the height of the stab elements because some of them + have emojis. + */ + min-height: 36px; + display: flex; + align-items: center; + white-space: pre-wrap; } .stab { padding: 3px; @@ -1121,6 +1128,7 @@ table, } .stab p { display: inline; + margin: 0; } .stab .emoji { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1751249fa62..7d7a63c5384 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -234,7 +234,7 @@ impl UrlFragment { &UrlFragment::Item(def_id) => { let kind = match tcx.def_kind(def_id) { DefKind::AssocFn => { - if tcx.associated_item(def_id).defaultness.has_value() { + if tcx.impl_defaultness(def_id).has_value() { "method." } else { "tymethod." diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index fd0b19034a2..0d968402503 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -304,6 +304,12 @@ pub(crate) fn run( let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates }; tcx.hir().visit_all_item_likes_in_crate(&mut finder); + // The visitor might have found a type error, which we need to + // promote to a fatal error + if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() { + return Err(String::from("Compilation failed, aborting rustdoc")); + } + // Sort call locations within a given file in document order for fn_calls in calls.values_mut() { for file_calls in fn_calls.values_mut() { diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 69883058335..1abbff32c6f 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -116,9 +116,9 @@ impl Foo { // Change Method Privacy ------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //---------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------ + //-------------------------- + //-------------------------------------------------------------- //-------------------------- pub fn method_privacy() { } } @@ -129,9 +129,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="associated_item")] + #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] fn method_privacy() { } } diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 9b79fd8a0a1..1988f3f3541 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -277,22 +277,22 @@ trait TraitChangeMethodParametersOrder { // Add default implementation to method #[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------- // ------------------------- fn method() ; } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() {} } @@ -795,20 +795,24 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { - type Associated; + //-------------------------------------------------------------- + //-------------------------- + //-------------------------------------------------------------- + //-------------------------- + type Associated ; fn method(); } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; @@ -839,20 +843,28 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant #[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { - const Value: u32; + //-------------------------------------------------------------- + //-------------------------- + //-------------------------------------------------------------- + //-------------------------- + const Value: u32 ; + //-------------------------- + //-------------------------- + //-------------------------- + //-------------------------- fn method(); } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index cc63aa4f556..f555f555f92 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -320,7 +320,11 @@ impl AddItemTrait for Foo { #[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { - fn method_name(); + //-------------------------------------------------------------- + //-------------------------- + //-------------------------------------------------------------- + //-------------------------- + fn method_name() ; } #[cfg(any(cfail1,cfail4))] @@ -329,14 +333,14 @@ impl ChangeHasValueTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail5")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { } } @@ -358,22 +362,22 @@ pub trait AddDefaultTrait { #[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - // ---------------------------------------------------- + // ------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------- + // ------------------------------------------------------------- // ------------------------- fn method_name() { } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { - #[rustc_clean(except="associated_item", cfg="cfail2")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="associated_item", cfg="cfail5")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] default fn method_name() { } } diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile index 4bb35f33ad3..17052ef4e63 100644 --- a/src/test/run-make-fulldeps/symbol-visibility/Makefile +++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile @@ -5,6 +5,7 @@ include ../tools.mk NM=nm -D CDYLIB_NAME=liba_cdylib.so RDYLIB_NAME=liba_rust_dylib.so +PROC_MACRO_NAME=liba_proc_macro.so EXE_NAME=an_executable COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so @@ -12,6 +13,7 @@ ifeq ($(UNAME),Darwin) NM=nm -gU CDYLIB_NAME=liba_cdylib.dylib RDYLIB_NAME=liba_rust_dylib.dylib +PROC_MACRO_NAME=liba_proc_macro.dylib EXE_NAME=an_executable COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib endif @@ -20,6 +22,7 @@ ifdef IS_WINDOWS NM=nm -g CDYLIB_NAME=liba_cdylib.dll.a RDYLIB_NAME=liba_rust_dylib.dll.a +PROC_MACRO_NAME=liba_proc_macro.dll EXE_NAME=an_executable.exe COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a endif @@ -31,6 +34,7 @@ all: $(RUSTC) -Zshare-generics=no an_rlib.rs $(RUSTC) -Zshare-generics=no a_cdylib.rs $(RUSTC) -Zshare-generics=no a_rust_dylib.rs + $(RUSTC) -Zshare-generics=no a_proc_macro.rs $(RUSTC) -Zshare-generics=no an_executable.rs $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib @@ -54,6 +58,14 @@ all: # Check that a Rust dylib does not export generics if -Zshare-generics=no [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ] + # Check that a proc macro exports its public #[no_mangle] functions + # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a proc macro exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a proc macro DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + # FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 ifndef IS_WINDOWS # Check that an executable does not export any dynamic symbols @@ -75,6 +87,7 @@ endif $(RUSTC) -Zshare-generics=yes an_rlib.rs $(RUSTC) -Zshare-generics=yes a_cdylib.rs $(RUSTC) -Zshare-generics=yes a_rust_dylib.rs + $(RUSTC) -Zshare-generics=yes a_proc_macro.rs $(RUSTC) -Zshare-generics=yes an_executable.rs # Check that a cdylib exports its public #[no_mangle] functions @@ -94,6 +107,14 @@ endif [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ] [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ] + # Check that a proc macro exports its public #[no_mangle] functions + # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] + # Check that a proc macro exports the public #[no_mangle] functions of dependencies + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] + # Check that a proc macro DOES NOT export any public Rust functions + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + ifndef IS_WINDOWS # Check that an executable does not export any dynamic symbols [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ] diff --git a/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs new file mode 100644 index 00000000000..9fd1a8a6717 --- /dev/null +++ b/src/test/run-make-fulldeps/symbol-visibility/a_proc_macro.rs @@ -0,0 +1,9 @@ +#![crate_type = "proc-macro"] + +extern crate an_rlib; + +// This should not be exported +#[no_mangle] +extern "C" fn public_c_function_from_cdylib() { + an_rlib::public_c_function_from_rlib(); +} diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile index 1badde54112..a254285ab76 100644 --- a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile +++ b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile @@ -14,10 +14,19 @@ ifdef IS_MSVC else $(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll endif - "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt + "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt ifdef RUSTC_BLESS_TEST cp "$(TMPDIR)"/output.txt output.txt else $(DIFF) output.txt "$(TMPDIR)"/output.txt endif + +ifdef IS_MSVC + "$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt +else + $(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt +endif +endif diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs index 3710507f5e4..b7f372c6b2b 100644 --- a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs +++ b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs @@ -1,5 +1,8 @@ extern crate raw_dylib_alt_calling_convention_test; fn main() { - raw_dylib_alt_calling_convention_test::library_function(); + raw_dylib_alt_calling_convention_test::library_function( + std::env::args().skip(1).next().map_or( + false, + |s| std::str::FromStr::from_str(&s).unwrap())); } diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c index 8f64abf2fb5..0c4d12af9b2 100644 --- a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c +++ b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c @@ -121,3 +121,58 @@ __declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) { printf("fastcall_fn_9(%d, %.1f)\n", x, y); fflush(stdout); } + +// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 +#ifdef _MSC_VER +__declspec(dllexport) void __vectorcall vectorcall_fn_1(int i) { + printf("vectorcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_2(uint8_t i, float f) { + printf("vectorcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_3(double d) { + printf("vectorcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("vectorcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_5(struct S s, int i) { + printf("vectorcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_6(struct S* s) { + if (s) { + printf("vectorcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("vectorcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_7(struct S2 s, int i) { + printf("vectorcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_8(struct S3 s, struct S3 t) { + printf("vectorcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_9(uint8_t x, double y) { + printf("vectorcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} +#endif diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs index 165792b0490..b5e9415b2be 100644 --- a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs +++ b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs @@ -1,4 +1,5 @@ #![feature(raw_dylib)] +#![feature(abi_vectorcall)] #[repr(C)] #[derive(Clone)] @@ -46,29 +47,60 @@ extern "fastcall" { fn fastcall_fn_9(x: u8, y: f64); } -pub fn library_function() { +#[cfg(target_env = "msvc")] +#[link(name = "extern", kind = "raw-dylib")] +extern "vectorcall" { + fn vectorcall_fn_1(i: i32); + fn vectorcall_fn_2(c: u8, f: f32); + fn vectorcall_fn_3(d: f64); + fn vectorcall_fn_4(i: u8, j: u8, f: f32); + fn vectorcall_fn_5(a: S, b: i32); + fn vectorcall_fn_6(a: Option<&S>); + fn vectorcall_fn_7(a: S2, b: i32); + fn vectorcall_fn_8(a: S3, b: S3); + fn vectorcall_fn_9(x: u8, y: f64); +} + +pub fn library_function(run_msvc_only: bool) { unsafe { - stdcall_fn_1(14); - stdcall_fn_2(16, 3.5); - stdcall_fn_3(3.5); - stdcall_fn_4(1, 2, 3.0); - stdcall_fn_5(S { x: 1, y: 2 }, 16); - stdcall_fn_6(Some(&S { x: 10, y: 12 })); - stdcall_fn_7(S2 { x: 15, y: 16 }, 3); - stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); - stdcall_fn_9(1, 3.0); + if !run_msvc_only { + stdcall_fn_1(14); + stdcall_fn_2(16, 3.5); + stdcall_fn_3(3.5); + stdcall_fn_4(1, 2, 3.0); + stdcall_fn_5(S { x: 1, y: 2 }, 16); + stdcall_fn_6(Some(&S { x: 10, y: 12 })); + stdcall_fn_7(S2 { x: 15, y: 16 }, 3); + stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + stdcall_fn_9(1, 3.0); + + fastcall_fn_1(14); + fastcall_fn_2(16, 3.5); + fastcall_fn_3(3.5); + fastcall_fn_4(1, 2, 3.0); + fastcall_fn_6(Some(&S { x: 10, y: 12 })); + fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + fastcall_fn_9(1, 3.0); + } else { + // FIXME: 91167 + // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7 + // on i686-pc-windows-gnu; disabling these until the indicated issue is fixed. + fastcall_fn_5(S { x: 1, y: 2 }, 16); + fastcall_fn_7(S2 { x: 15, y: 16 }, 3); - fastcall_fn_1(14); - fastcall_fn_2(16, 3.5); - fastcall_fn_3(3.5); - fastcall_fn_4(1, 2, 3.0); - // FIXME: 91167 - // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7 - // on i686-pc-windows-gnu; commenting these out until the indicated issue is fixed. - //fastcall_fn_5(S { x: 1, y: 2 }, 16); - fastcall_fn_6(Some(&S { x: 10, y: 12 })); - //fastcall_fn_7(S2 { x: 15, y: 16 }, 3); - fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); - fastcall_fn_9(1, 3.0); + // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 + #[cfg(target_env = "msvc")] + { + vectorcall_fn_1(14); + vectorcall_fn_2(16, 3.5); + vectorcall_fn_3(3.5); + vectorcall_fn_4(1, 2, 3.0); + vectorcall_fn_5(S { x: 1, y: 2 }, 16); + vectorcall_fn_6(Some(&S { x: 10, y: 12 })); + vectorcall_fn_7(S2 { x: 15, y: 16 }, 3); + vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + vectorcall_fn_9(1, 3.0); + } + } } } diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt new file mode 100644 index 00000000000..9ddd1b11016 --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/output.msvc.txt @@ -0,0 +1,11 @@ +fastcall_fn_5(S { x: 1, y: 2 }, 16) +fastcall_fn_7(S2 { x: 15, y: 16 }, 3) +vectorcall_fn_1(14) +vectorcall_fn_2(16, 3.5) +vectorcall_fn_3(3.5) +vectorcall_fn_4(1, 2, 3.0) +vectorcall_fn_5(S { x: 1, y: 2 }, 16) +vectorcall_fn_6(S { x: 10, y: 12 }) +vectorcall_fn_7(S2 { x: 15, y: 16 }, 3) +vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +vectorcall_fn_9(1, 3.0) diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml deleted file mode 100644 index 8b6d355a8f1..00000000000 --- a/src/test/rustdoc-gui/item-info-width.goml +++ /dev/null @@ -1,8 +0,0 @@ -// This test ensures that the item information don't take 100% of the width if unnecessary. -goto: file://|DOC_PATH|/lib2/struct.Foo.html -// We set a fixed size so there is no chance of "random" resize. -size: (1100, 800) -// We check that ".item-info" is bigger than its content. -assert-css: (".item-info", {"width": "790px"}) -assert-css: (".item-info .stab", {"width": "289px"}) -assert-position: (".item-info .stab", {"x": 295}) diff --git a/src/test/rustdoc-gui/item-info.goml b/src/test/rustdoc-gui/item-info.goml new file mode 100644 index 00000000000..50c45b76bd6 --- /dev/null +++ b/src/test/rustdoc-gui/item-info.goml @@ -0,0 +1,32 @@ +// This test ensures a few things for item info elements. +goto: file://|DOC_PATH|/lib2/struct.Foo.html +// Ensuring that the item information don't take 100% of the width if unnecessary. +// We set a fixed size so there is no chance of "random" resize. +size: (1100, 800) +// We check that ".item-info" is bigger than its content. +assert-css: (".item-info", {"width": "790px"}) +assert-css: (".item-info .stab", {"width": "289px"}) +assert-position: (".item-info .stab", {"x": 295}) + +// Now we ensure that they're not rendered on the same line. +goto: file://|DOC_PATH|/lib2/trait.Trait.html +// We first ensure that there are two item info on the trait. +assert-count: ("#main-content > .item-info .stab", 2) +// They should not have the same `y` position! +compare-elements-position-false: ( + "#main-content > .item-info .stab:nth-of-type(1)", + "#main-content > .item-info .stab:nth-of-type(2)", + ("y"), +) +// But they should have the same `x` position. +compare-elements-position: ( + "#main-content > .item-info .stab:nth-of-type(1)", + "#main-content > .item-info .stab:nth-of-type(2)", + ("x"), +) +// They are supposed to have the same height too. +compare-elements-css: ( + "#main-content > .item-info .stab:nth-of-type(1)", + "#main-content > .item-info .stab:nth-of-type(2)", + ["height"], +) diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 4546449e102..87f91be3ac8 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -30,10 +30,13 @@ impl Foo { pub fn a_method(&self) {} } +#[doc(cfg(feature = "foo-method"))] +#[deprecated = "Whatever [`Foo::a_method`](#method.a_method)"] pub trait Trait { type X; const Y: u32; + #[deprecated = "Whatever [`Foo`](#tadam)"] fn foo() {} } diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs new file mode 100644 index 00000000000..8f4fde96d7e --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.rs @@ -0,0 +1,7 @@ +// check-fail +// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar + +pub fn foo() { + INVALID_FUNC(); + //~^ ERROR could not resolve path +} diff --git a/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr new file mode 100644 index 00000000000..750aa320719 --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-fail-if-type-error.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: could not resolve path `INVALID_FUNC` + --> $DIR/scrape-examples-fail-if-type-error.rs:5:3 + | +LL | INVALID_FUNC(); + | ^^^^^^^^^^^^ could not resolve path `INVALID_FUNC` + | + = note: this error was originally ignored because you are running `rustdoc` + = note: try running again with `rustc` or `cargo check` and you may get a more detailed error + +error: Compilation failed, aborting rustdoc + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index c8e5cac0594..6dc41231559 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -69,7 +69,7 @@ -Z link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no) -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated) -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) - -Z location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all) + -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`) -Z ls=val -- list the symbols defined by a library crate (default: no) -Z macro-backtrace=val -- show macro backtraces (default: no) -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index fd76c282f96..e6f6e9e9f65 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -35,7 +35,7 @@ note: cycle used when checking item types in top-level module --> $DIR/no-const-async.rs:4:1 | LL | pub const async fn x() {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/access-mode-in-closures.stderr b/src/test/ui/borrowck/access-mode-in-closures.stderr index c32e944afe3..13a6277da14 100644 --- a/src/test/ui/borrowck/access-mode-in-closures.stderr +++ b/src/test/ui/borrowck/access-mode-in-closures.stderr @@ -1,4 +1,4 @@ -error[E0507]: cannot move out of `s.0` which is behind a shared reference +error[E0507]: cannot move out of `s` which is behind a shared reference --> $DIR/access-mode-in-closures.rs:8:15 | LL | match *s { S(v) => v } diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr index ead02414a62..96246d9ae1a 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr @@ -1,4 +1,4 @@ -error[E0507]: cannot move out of `f.0` which is behind a shared reference +error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference --> $DIR/borrowck-move-error-with-note.rs:11:11 | LL | match *f { diff --git a/src/test/ui/check-cfg/invalid-cfg-value.rs b/src/test/ui/check-cfg/invalid-cfg-value.rs index a60095a5aae..9e428d367fd 100644 --- a/src/test/ui/check-cfg/invalid-cfg-value.rs +++ b/src/test/ui/check-cfg/invalid-cfg-value.rs @@ -12,6 +12,7 @@ pub fn f() {} pub fn g() {} #[cfg(feature = "rand")] +//~^ WARNING unexpected `cfg` condition value pub fn h() {} pub fn main() {} diff --git a/src/test/ui/check-cfg/invalid-cfg-value.stderr b/src/test/ui/check-cfg/invalid-cfg-value.stderr index bc2c053fed6..6cce31d3392 100644 --- a/src/test/ui/check-cfg/invalid-cfg-value.stderr +++ b/src/test/ui/check-cfg/invalid-cfg-value.stderr @@ -5,7 +5,15 @@ LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^^^^^^^^ | = note: `#[warn(unexpected_cfgs)]` on by default - = note: expected values for `feature` are: full, rand, serde + = note: expected values for `feature` are: full, serde -warning: 1 warning emitted +warning: unexpected `cfg` condition value + --> $DIR/invalid-cfg-value.rs:14:7 + | +LL | #[cfg(feature = "rand")] + | ^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: full, serde + +warning: 2 warnings emitted diff --git a/src/test/ui/check-cfg/mix.rs b/src/test/ui/check-cfg/mix.rs index b51d356f61f..8e3d20d5045 100644 --- a/src/test/ui/check-cfg/mix.rs +++ b/src/test/ui/check-cfg/mix.rs @@ -1,6 +1,6 @@ -// This test checks the combination of well known names, their activation via names(), the usage of -// partial values() with a --cfg and test that we also correctly lint on the `cfg!` macro and -// `cfg_attr` attribute. +// This test checks the combination of well known names, their activation via names(), +// the usage of values(), and that no implicit is done with --cfg while also testing that +// we correctly lint on the `cfg!` macro and `cfg_attr` attribute. // // check-pass // compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options @@ -16,6 +16,7 @@ fn do_windows_stuff() {} fn use_foo() {} #[cfg(feature = "bar")] +//~^ WARNING unexpected `cfg` condition value fn use_bar() {} #[cfg(feature = "zebra")] @@ -35,6 +36,7 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition name cfg!(feature = "foo"); cfg!(feature = "bar"); + //~^ WARNING unexpected `cfg` condition value cfg!(feature = "zebra"); //~^ WARNING unexpected `cfg` condition value cfg!(xxx = "foo"); diff --git a/src/test/ui/check-cfg/mix.stderr b/src/test/ui/check-cfg/mix.stderr index 08a338da104..e51b75b3d43 100644 --- a/src/test/ui/check-cfg/mix.stderr +++ b/src/test/ui/check-cfg/mix.stderr @@ -7,21 +7,29 @@ LL | #[cfg(widnows)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value - --> $DIR/mix.rs:21:7 + --> $DIR/mix.rs:18:7 + | +LL | #[cfg(feature = "bar")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:22:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition name - --> $DIR/mix.rs:25:12 + --> $DIR/mix.rs:26:12 | LL | #[cfg_attr(uu, test)] | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:34:10 + --> $DIR/mix.rs:35:10 | LL | cfg!(widnows); | ^^^^^^^ help: did you mean: `windows` @@ -29,132 +37,138 @@ LL | cfg!(widnows); warning: unexpected `cfg` condition value --> $DIR/mix.rs:38:10 | +LL | cfg!(feature = "bar"); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:40:10 + | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition name - --> $DIR/mix.rs:40:10 + --> $DIR/mix.rs:42:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:42:10 + --> $DIR/mix.rs:44:10 | LL | cfg!(xxx); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:44:14 + --> $DIR/mix.rs:46:14 | LL | cfg!(any(xxx, windows)); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:46:14 + --> $DIR/mix.rs:48:14 | LL | cfg!(any(feature = "bad", windows)); - | ^^^^^^^^^^----- - | | - | help: did you mean: `"bar"` + | ^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition name - --> $DIR/mix.rs:48:23 + --> $DIR/mix.rs:50:23 | LL | cfg!(any(windows, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:50:20 + --> $DIR/mix.rs:52:20 | LL | cfg!(all(unix, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:52:14 + --> $DIR/mix.rs:54:14 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:52:18 + --> $DIR/mix.rs:54:18 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:55:14 + --> $DIR/mix.rs:57:14 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:55:18 + --> $DIR/mix.rs:57:18 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:58:20 + --> $DIR/mix.rs:60:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition name - --> $DIR/mix.rs:60:14 + --> $DIR/mix.rs:62:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:60:19 + --> $DIR/mix.rs:62:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition name - --> $DIR/mix.rs:63:14 + --> $DIR/mix.rs:65:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:63:25 + --> $DIR/mix.rs:65:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:66:14 + --> $DIR/mix.rs:68:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition value - --> $DIR/mix.rs:66:33 + --> $DIR/mix.rs:68:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo warning: unexpected `cfg` condition value - --> $DIR/mix.rs:66:52 + --> $DIR/mix.rs:68:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: bar, foo + = note: expected values for `feature` are: foo -warning: 23 warnings emitted +warning: 25 warnings emitted diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr index c085beb0ea5..57f94f8c6ab 100644 --- a/src/test/ui/consts/issue-44415.stderr +++ b/src/test/ui/consts/issue-44415.stderr @@ -2,18 +2,18 @@ error[E0391]: cycle detected when evaluating type-level constant --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }], - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }], - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }], - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires computing layout of `[u8; _]`... = note: ...which requires normalizing `[u8; _]`... diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr index fc842fada5a..d4976a0f9c9 100644 --- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr @@ -8,8 +8,13 @@ LL | trait Foo<X = Box<dyn Foo>> { note: cycle used when collecting item types in top-level module --> $DIR/cycle-trait-default-type-trait.rs:4:1 | -LL | trait Foo<X = Box<dyn Foo>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Foo<X = Box<dyn Foo>> { +LL | | +LL | | +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ error[E0391]: cycle detected when computing type of `Foo::X` --> $DIR/cycle-trait-default-type-trait.rs:4:23 @@ -21,8 +26,13 @@ LL | trait Foo<X = Box<dyn Foo>> { note: cycle used when collecting item types in top-level module --> $DIR/cycle-trait-default-type-trait.rs:4:1 | -LL | trait Foo<X = Box<dyn Foo>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Foo<X = Box<dyn Foo>> { +LL | | +LL | | +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ error: aborting due to 2 previous errors diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr index ee54b2fd151..f6ffcc4b5aa 100644 --- a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -13,8 +13,10 @@ LL | trait Chromosome: Chromosome { note: cycle used when collecting item types in top-level module --> $DIR/cycle-trait-supertrait-direct.rs:3:1 | -LL | trait Chromosome: Chromosome { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait Chromosome: Chromosome { +LL | | +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs index 5d7c611980f..b1c7dc2a7f6 100644 --- a/src/test/ui/did_you_mean/compatible-variants.rs +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -66,7 +66,7 @@ fn main() { } enum A { - B { b: B}, + B { b: B }, } struct A2(B); @@ -77,13 +77,12 @@ enum B { } fn foo() { - // We don't want to suggest `A::B(B::Fst)` here. let a: A = B::Fst; //~^ ERROR mismatched types + //~| HELP try wrapping } fn bar() { - // But we _do_ want to suggest `A2(B::Fst)` here! let a: A2 = B::Fst; //~^ ERROR mismatched types //~| HELP try wrapping diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr index a16cdee4462..fe81da19833 100644 --- a/src/test/ui/did_you_mean/compatible-variants.stderr +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -191,15 +191,20 @@ LL | let _ = Foo { bar: Some(bar) }; | ++++++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:81:16 + --> $DIR/compatible-variants.rs:80:16 | LL | let a: A = B::Fst; | - ^^^^^^ expected enum `A`, found enum `B` | | | expected due to this + | +help: try wrapping the expression in `A::B` + | +LL | let a: A = A::B { b: B::Fst }; + | +++++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:87:17 + --> $DIR/compatible-variants.rs:86:17 | LL | let a: A2 = B::Fst; | -- ^^^^^^ expected struct `A2`, found enum `B` diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs index 6da640b2b7c..eb96c248063 100644 --- a/src/test/ui/did_you_mean/issue-42764.rs +++ b/src/test/ui/did_you_mean/issue-42764.rs @@ -26,4 +26,5 @@ struct Context { wrapper: Wrapper } fn overton() { let _c = Context { wrapper: Payload{} }; //~^ ERROR mismatched types + //~| try wrapping the expression in `Wrapper` } diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index 95b572133c5..6a7fd8fe251 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -25,6 +25,11 @@ error[E0308]: mismatched types | LL | let _c = Context { wrapper: Payload{} }; | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload` + | +help: try wrapping the expression in `Wrapper` + | +LL | let _c = Context { wrapper: Wrapper { payload: Payload{} } }; + | ++++++++++++++++++ + error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 68da46d46bd..1461e7fd2dd 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -4,12 +4,10 @@ warning: function cannot return without recursing LL | / fn no_hrtb<'b, T>(mut t: T) LL | | where LL | | T: Bar<&'b isize>, -LL | | { -... | -LL | | no_hrtb(&mut t); - | | --------------- recursive call site -LL | | } - | |_^ cannot return without recursing + | |______________________^ cannot return without recursing +... +LL | no_hrtb(&mut t); + | --------------- recursive call site | = note: `#[warn(unconditional_recursion)]` on by default = help: a `loop` may express intention better if this is on purpose @@ -20,12 +18,10 @@ warning: function cannot return without recursing LL | / fn bar_hrtb<T>(mut t: T) LL | | where LL | | T: for<'b> Bar<&'b isize>, -LL | | { -... | -LL | | bar_hrtb(&mut t); - | | ---------------- recursive call site -LL | | } - | |_^ cannot return without recursing + | |______________________________^ cannot return without recursing +... +LL | bar_hrtb(&mut t); + | ---------------- recursive call site | = help: a `loop` may express intention better if this is on purpose @@ -35,14 +31,10 @@ warning: function cannot return without recursing LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T) LL | | where LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, -LL | | { -... | -LL | | foo_hrtb_bar_not(&mut t); - | | ------------------------ recursive call site -LL | | -LL | | -LL | | } - | |_^ cannot return without recursing + | |_______________________________________________^ cannot return without recursing +... +LL | foo_hrtb_bar_not(&mut t); + | ------------------------ recursive call site | = help: a `loop` may express intention better if this is on purpose @@ -70,12 +62,10 @@ warning: function cannot return without recursing LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T) LL | | where LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, -LL | | { -LL | | // OK -- now we have `T : for<'b> Bar<&'b isize>`. -LL | | foo_hrtb_bar_hrtb(&mut t); - | | ------------------------- recursive call site -LL | | } - | |_^ cannot return without recursing + | |_______________________________________________________^ cannot return without recursing +... +LL | foo_hrtb_bar_hrtb(&mut t); + | ------------------------- recursive call site | = help: a `loop` may express intention better if this is on purpose diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr index 5f2b98c5237..789a1141c04 100644 --- a/src/test/ui/issues/issue-12511.stderr +++ b/src/test/ui/issues/issue-12511.stderr @@ -23,8 +23,10 @@ LL | trait T2 : T1 { note: cycle used when collecting item types in top-level module --> $DIR/issue-12511.rs:1:1 | -LL | trait T1 : T2 { - | ^^^^^^^^^^^^^ +LL | / trait T1 : T2 { +LL | | +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 7ba9657fcd6..c5e1c41d130 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -1,4 +1,12 @@ error: layout_of(E) = Layout { + size: Size(12 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +15,16 @@ error: layout_of(E) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,24 +37,30 @@ error: layout_of(E) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(12 bytes), align: AbiAndPrefAlign { - abi: Align(1 bytes), + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size(4 bytes), - }, - Layout { + abi: Uninhabited, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -49,37 +73,13 @@ error: layout_of(E) = Layout { 2, ], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Uninhabited, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(12 bytes), }, ], }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - false, - ), - valid_range: 0..=0, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(12 bytes), } --> $DIR/debug.rs:6:1 | @@ -87,20 +87,10 @@ LL | enum E { Foo, Bar(!, i32, i32) } | ^^^^^^ error: layout_of(S) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - Size(0 bytes), - Size(4 bytes), - ], - memory_index: [ - 1, - 0, - 2, - ], - }, - variants: Single { - index: 0, + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -118,12 +108,22 @@ error: layout_of(S) = Layout { valid_range: 0..=4294967295, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + Size(0 bytes), + Size(4 bytes), + ], + memory_index: [ + 1, + 0, + 2, + ], + }, largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 0, }, - size: Size(8 bytes), } --> $DIR/debug.rs:9:1 | @@ -131,21 +131,21 @@ LL | struct S { f1: i32, f2: (), f3: i32 } | ^^^^^^^^ error: layout_of(U) = Layout { - fields: Union( - 2, - ), - variants: Single { - index: 0, + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, }, abi: Aggregate { sized: true, }, + fields: Union( + 2, + ), largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 0, }, - size: Size(8 bytes), } --> $DIR/debug.rs:12:1 | @@ -153,6 +153,27 @@ LL | union U { f1: (i32, i32), f3: i32 } | ^^^^^^^ error: layout_of(std::result::Result<i32, i32>) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -161,6 +182,16 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -173,16 +204,10 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(4 bytes), - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 0, + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -200,14 +225,6 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { valid_range: 0..=4294967295, }, ), - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(8 bytes), - }, - Layout { fields: Arbitrary { offsets: [ Size(4 bytes), @@ -216,8 +233,16 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { 0, ], }, + largest_niche: None, variants: Single { - index: 1, + index: 0, + }, + }, + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -235,46 +260,21 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { valid_range: 0..=4294967295, }, ), + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(8 bytes), }, ], }, - abi: ScalarPair( - Initialized { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, - Initialized { - value: Int( - I32, - true, - ), - valid_range: 0..=4294967295, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(8 bytes), } --> $DIR/debug.rs:15:1 | @@ -282,9 +282,10 @@ LL | type Test = Result<i32, i32>; | ^^^^^^^^^ error: layout_of(i32) = Layout { - fields: Primitive, - variants: Single { - index: 0, + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, }, abi: Scalar( Initialized { @@ -295,12 +296,11 @@ error: layout_of(i32) = Layout { valid_range: 0..=4294967295, }, ), + fields: Primitive, largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 0, }, - size: Size(4 bytes), } --> $DIR/debug.rs:18:1 | diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index f3123cb0ad2..d850dd69c96 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -1,4 +1,18 @@ error: layout_of(A) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +21,16 @@ error: layout_of(A) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,34 +43,54 @@ error: layout_of(A) = Layout { tag_field: 0, variants: [ Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(1 bytes), - }, - size: Size(1 bytes), }, ], }, + } + --> $DIR/hexagon-enum.rs:16:1 + | +LL | enum A { Apple } + | ^^^^^^ + +error: layout_of(B) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, abi: Scalar( Initialized { value: Int( I8, false, ), - valid_range: 0..=0, + valid_range: 255..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -54,29 +98,9 @@ error: layout_of(A) = Layout { I8, false, ), - valid_range: 0..=0, + valid_range: 255..=255, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(1 bytes), - }, - size: Size(1 bytes), - } - --> $DIR/hexagon-enum.rs:16:1 - | -LL | enum A { Apple } - | ^^^^^^ - -error: layout_of(B) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - ], - memory_index: [ - 0, - ], - }, variants: Multiple { tag: Initialized { value: Int( @@ -89,49 +113,25 @@ error: layout_of(B) = Layout { tag_field: 0, variants: [ Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(1 bytes), - }, - size: Size(1 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(1 bytes), - }, - size: Size(1 bytes), } --> $DIR/hexagon-enum.rs:20:1 | @@ -139,6 +139,20 @@ LL | enum B { Banana = 255, } | ^^^^^^ error: layout_of(C) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(2 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -147,6 +161,16 @@ error: layout_of(C) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -159,49 +183,25 @@ error: layout_of(C) = Layout { tag_field: 0, variants: [ Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(2 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(2 bytes), - pref: Align(2 bytes), - }, - size: Size(2 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - align: AbiAndPrefAlign { - abi: Align(2 bytes), - pref: Align(2 bytes), - }, - size: Size(2 bytes), } --> $DIR/hexagon-enum.rs:24:1 | @@ -209,6 +209,20 @@ LL | enum C { Chaenomeles = 256, } | ^^^^^^ error: layout_of(P) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -217,6 +231,16 @@ error: layout_of(P) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -229,49 +253,25 @@ error: layout_of(P) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), } --> $DIR/hexagon-enum.rs:28:1 | @@ -279,6 +279,20 @@ LL | enum P { Peach = 0x1000_0000isize, } | ^^^^^^ error: layout_of(T) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -287,6 +301,16 @@ error: layout_of(T) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -299,49 +323,25 @@ error: layout_of(T) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), } --> $DIR/hexagon-enum.rs:34:1 | diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 84d8bc799b9..6deb1f271a7 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -1,4 +1,24 @@ error: layout_of(MissingPayloadField) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +27,16 @@ error: layout_of(MissingPayloadField) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,16 +49,10 @@ error: layout_of(MissingPayloadField) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(1 bytes), - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 0, + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -45,33 +69,51 @@ error: layout_of(MissingPayloadField) = Layout { ), }, ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(1 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(2 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(1 bytes), }, ], }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 + | +LL | pub enum MissingPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(CommonPayloadField) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, abi: ScalarPair( Initialized { value: Int( @@ -80,13 +122,22 @@ error: layout_of(MissingPayloadField) = Layout { ), valid_range: 0..=1, }, - Union { + Initialized { value: Int( I8, false, ), + valid_range: 0..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -97,26 +148,6 @@ error: layout_of(MissingPayloadField) = Layout { valid_range: 0..=1, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - } - --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 - | -LL | pub enum MissingPayloadField { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: layout_of(CommonPayloadField) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - ], - memory_index: [ - 0, - ], - }, variants: Multiple { tag: Initialized { value: Int( @@ -129,16 +160,10 @@ error: layout_of(CommonPayloadField) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(1 bytes), - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 0, + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -156,14 +181,6 @@ error: layout_of(CommonPayloadField) = Layout { valid_range: 0..=255, }, ), - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - }, - Layout { fields: Arbitrary { offsets: [ Size(1 bytes), @@ -172,8 +189,16 @@ error: layout_of(CommonPayloadField) = Layout { 0, ], }, + largest_niche: None, variants: Single { - index: 1, + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -191,15 +216,33 @@ error: layout_of(CommonPayloadField) = Layout { valid_range: 0..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(2 bytes), }, ], }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 + | +LL | pub enum CommonPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, abi: ScalarPair( Initialized { value: Int( @@ -208,14 +251,21 @@ error: layout_of(CommonPayloadField) = Layout { ), valid_range: 0..=1, }, - Initialized { + Union { value: Int( I8, false, ), - valid_range: 0..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -226,26 +276,6 @@ error: layout_of(CommonPayloadField) = Layout { valid_range: 0..=1, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - } - --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 - | -LL | pub enum CommonPayloadField { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - ], - memory_index: [ - 0, - ], - }, variants: Multiple { tag: Initialized { value: Int( @@ -258,16 +288,10 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(1 bytes), - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 0, + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -284,14 +308,6 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ), }, ), - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - }, - Layout { fields: Arbitrary { offsets: [ Size(1 bytes), @@ -300,8 +316,16 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { 0, ], }, + largest_niche: None, variants: Single { - index: 1, + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -318,22 +342,40 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ), }, ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(2 bytes), }, ], }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 + | +LL | pub enum CommonPayloadFieldIsMaybeUninit { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(NicheFirst) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, abi: ScalarPair( Initialized { value: Int( I8, false, ), - valid_range: 0..=1, + valid_range: 0..=4, }, Union { value: Int( @@ -342,6 +384,14 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ), }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -349,29 +399,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { I8, false, ), - valid_range: 0..=1, + valid_range: 0..=4, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - } - --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 - | -LL | pub enum CommonPayloadFieldIsMaybeUninit { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: layout_of(NicheFirst) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - ], - memory_index: [ - 0, - ], - }, variants: Multiple { tag: Initialized { value: Int( @@ -388,18 +418,10 @@ error: layout_of(NicheFirst) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - Size(1 bytes), - ], - memory_index: [ - 0, - 1, - ], - }, - variants: Single { - index: 0, + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -417,6 +439,16 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + Size(1 bytes), + ], + memory_index: [ + 0, + 1, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -427,68 +459,68 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=2, }, ), + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(2 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(0 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 2, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(0 bytes), }, ], }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 + | +LL | pub enum NicheFirst { + | ^^^^^^^^^^^^^^^^^^^ + +error: layout_of(NicheSecond) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, abi: ScalarPair( - Initialized { - value: Int( - I8, - false, - ), - valid_range: 0..=4, - }, Union { value: Int( I8, false, ), }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), + Initialized { value: Int( I8, false, @@ -496,18 +528,6 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=4, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), - } - --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 - | -LL | pub enum NicheFirst { - | ^^^^^^^^^^^^^^^^^^^ - -error: layout_of(NicheSecond) = Layout { fields: Arbitrary { offsets: [ Size(1 bytes), @@ -516,6 +536,16 @@ error: layout_of(NicheSecond) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -532,18 +562,10 @@ error: layout_of(NicheSecond) = Layout { tag_field: 0, variants: [ Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - Size(1 bytes), - ], - memory_index: [ - 0, - 1, - ], - }, - variants: Single { - index: 0, + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, abi: ScalarPair( Initialized { @@ -561,6 +583,16 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=2, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + Size(1 bytes), + ], + memory_index: [ + 0, + 1, + ], + }, largest_niche: Some( Niche { offset: Size(1 bytes), @@ -571,80 +603,48 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=2, }, ), + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(2 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(0 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 2, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(0 bytes), }, ], }, - abi: ScalarPair( - Union { - value: Int( - I8, - false, - ), - }, - Initialized { - value: Int( - I8, - false, - ), - valid_range: 0..=4, - }, - ), - largest_niche: Some( - Niche { - offset: Size(1 bytes), - value: Int( - I8, - false, - ), - valid_range: 0..=4, - }, - ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 | diff --git a/src/test/ui/layout/issue-96185-overaligned-enum.stderr b/src/test/ui/layout/issue-96185-overaligned-enum.stderr index 8dc364fa7c9..de6177c8dfc 100644 --- a/src/test/ui/layout/issue-96185-overaligned-enum.stderr +++ b/src/test/ui/layout/issue-96185-overaligned-enum.stderr @@ -1,4 +1,12 @@ error: layout_of(Aligned1) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +15,16 @@ error: layout_of(Aligned1) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,49 +37,57 @@ error: layout_of(Aligned1) = Layout { tag_field: 0, variants: [ Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, - size: Size(8 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(8 bytes), - pref: $PREF_ALIGN, - }, - size: Size(8 bytes), }, ], }, - abi: Aggregate { - sized: true, + } + --> $DIR/issue-96185-overaligned-enum.rs:8:1 + | +LL | pub enum Aligned1 { + | ^^^^^^^^^^^^^^^^^ + +error: layout_of(Aligned2) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), + abi: Scalar( + Initialized { value: Int( I8, false, @@ -69,18 +95,6 @@ error: layout_of(Aligned1) = Layout { valid_range: 0..=1, }, ), - align: AbiAndPrefAlign { - abi: Align(8 bytes), - pref: $PREF_ALIGN, - }, - size: Size(8 bytes), - } - --> $DIR/issue-96185-overaligned-enum.rs:8:1 - | -LL | pub enum Aligned1 { - | ^^^^^^^^^^^^^^^^^ - -error: layout_of(Aligned2) = Layout { fields: Arbitrary { offsets: [ Size(0 bytes), @@ -89,6 +103,16 @@ error: layout_of(Aligned2) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -101,67 +125,43 @@ error: layout_of(Aligned2) = Layout { tag_field: 0, variants: [ Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(1 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(1 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(1 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I8, - false, - ), - valid_range: 0..=1, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 0..=1, - }, - ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, - }, - size: Size(1 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:16:1 | diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index e6ed626d5f1..227bd950b66 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr @@ -1,4 +1,18 @@ error: layout_of(A) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +21,16 @@ error: layout_of(A) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,34 +43,54 @@ error: layout_of(A) = Layout { tag_field: 0, variants: [ Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(4 bytes), - }, - size: Size(1 bytes), }, ], }, + } + --> $DIR/thumb-enum.rs:16:1 + | +LL | enum A { Apple } + | ^^^^^^ + +error: layout_of(B) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, abi: Scalar( Initialized { value: Int( I8, false, ), - valid_range: 0..=0, + valid_range: 255..=255, }, ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -54,29 +98,9 @@ error: layout_of(A) = Layout { I8, false, ), - valid_range: 0..=0, + valid_range: 255..=255, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(4 bytes), - }, - size: Size(1 bytes), - } - --> $DIR/thumb-enum.rs:16:1 - | -LL | enum A { Apple } - | ^^^^^^ - -error: layout_of(B) = Layout { - fields: Arbitrary { - offsets: [ - Size(0 bytes), - ], - memory_index: [ - 0, - ], - }, variants: Multiple { tag: Initialized { value: Int( @@ -89,49 +113,25 @@ error: layout_of(B) = Layout { tag_field: 0, variants: [ Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(4 bytes), - }, - size: Size(1 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: Align(4 bytes), - }, - size: Size(1 bytes), } --> $DIR/thumb-enum.rs:20:1 | @@ -139,6 +139,20 @@ LL | enum B { Banana = 255, } | ^^^^^^ error: layout_of(C) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -147,6 +161,16 @@ error: layout_of(C) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -159,49 +183,25 @@ error: layout_of(C) = Layout { tag_field: 0, variants: [ Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(2 bytes), - pref: Align(4 bytes), - }, - size: Size(2 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - align: AbiAndPrefAlign { - abi: Align(2 bytes), - pref: Align(4 bytes), - }, - size: Size(2 bytes), } --> $DIR/thumb-enum.rs:24:1 | @@ -209,6 +209,20 @@ LL | enum C { Chaenomeles = 256, } | ^^^^^^ error: layout_of(P) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -217,6 +231,16 @@ error: layout_of(P) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -229,49 +253,25 @@ error: layout_of(P) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), } --> $DIR/thumb-enum.rs:28:1 | @@ -279,6 +279,20 @@ LL | enum P { Peach = 0x1000_0000isize, } | ^^^^^^ error: layout_of(T) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -287,6 +301,16 @@ error: layout_of(T) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -299,49 +323,25 @@ error: layout_of(T) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [], memory_index: [], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), }, ], }, - abi: Scalar( - Initialized { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: Align(4 bytes), - }, - size: Size(4 bytes), } --> $DIR/thumb-enum.rs:34:1 | diff --git a/src/test/ui/layout/zero-sized-array-enum-niche.stderr b/src/test/ui/layout/zero-sized-array-enum-niche.stderr index 0dbecbe412b..56d3a52bb7f 100644 --- a/src/test/ui/layout/zero-sized-array-enum-niche.stderr +++ b/src/test/ui/layout/zero-sized-array-enum-niche.stderr @@ -1,4 +1,12 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -7,6 +15,16 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -19,6 +37,14 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -27,20 +53,20 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { 0, ], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(2 bytes), align: AbiAndPrefAlign { - abi: Align(4 bytes), + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(4 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(1 bytes), @@ -49,12 +75,6 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { 0, ], }, - variants: Single { - index: 1, - }, - abi: Aggregate { - sized: true, - }, largest_niche: Some( Niche { offset: Size(1 bytes), @@ -65,32 +85,12 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { valid_range: 0..=1, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(2 bytes), }, ], }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 0..=1, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:13:1 | @@ -98,6 +98,14 @@ LL | type AlignedResult = Result<[u32; 0], bool>; | ^^^^^^^^^^^^^^^^^^ error: layout_of(MultipleAlignments) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -106,6 +114,16 @@ error: layout_of(MultipleAlignments) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -118,6 +136,14 @@ error: layout_of(MultipleAlignments) = Layout { tag_field: 0, variants: [ Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(2 bytes), @@ -126,20 +152,20 @@ error: layout_of(MultipleAlignments) = Layout { 0, ], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(4 bytes), align: AbiAndPrefAlign { - abi: Align(2 bytes), + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size(2 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -148,20 +174,20 @@ error: layout_of(MultipleAlignments) = Layout { 0, ], }, + largest_niche: None, variants: Single { index: 1, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(2 bytes), align: AbiAndPrefAlign { - abi: Align(4 bytes), + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(4 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(1 bytes), @@ -170,12 +196,6 @@ error: layout_of(MultipleAlignments) = Layout { 0, ], }, - variants: Single { - index: 2, - }, - abi: Aggregate { - sized: true, - }, largest_niche: Some( Niche { offset: Size(1 bytes), @@ -186,32 +206,12 @@ error: layout_of(MultipleAlignments) = Layout { valid_range: 0..=1, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 2, }, - size: Size(2 bytes), }, ], }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 0..=2, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:21:1 | @@ -219,6 +219,14 @@ LL | enum MultipleAlignments { | ^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -227,6 +235,16 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -239,6 +257,14 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = tag_field: 0, variants: [ Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -247,20 +273,20 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = 0, ], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(3 bytes), align: AbiAndPrefAlign { - abi: Align(4 bytes), + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(4 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(1 bytes), @@ -269,12 +295,6 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = 0, ], }, - variants: Single { - index: 1, - }, - abi: Aggregate { - sized: true, - }, largest_niche: Some( Niche { offset: Size(1 bytes), @@ -285,32 +305,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed<std::num::NonZeroU16>>) = valid_range: 1..=65535, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(3 bytes), }, ], }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I8, - false, - ), - valid_range: 0..=1, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:37:1 | @@ -318,6 +318,14 @@ LL | type NicheLosesToTagged = Result<[u32; 0], Packed<std::num::NonZeroU16>>; | ^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -326,6 +334,16 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { 0, ], }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 0..=1, + }, + ), variants: Multiple { tag: Initialized { value: Int( @@ -342,6 +360,14 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { tag_field: 0, variants: [ Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -350,20 +376,20 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { 0, ], }, + largest_niche: None, variants: Single { index: 0, }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, + }, + Layout { + size: Size(2 bytes), align: AbiAndPrefAlign { - abi: Align(4 bytes), + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size(0 bytes), - }, - Layout { + abi: Aggregate { + sized: true, + }, fields: Arbitrary { offsets: [ Size(0 bytes), @@ -372,12 +398,6 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { 0, ], }, - variants: Single { - index: 1, - }, - abi: Aggregate { - sized: true, - }, largest_niche: Some( Niche { offset: Size(0 bytes), @@ -388,32 +408,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { valid_range: 0..=0, }, ), - align: AbiAndPrefAlign { - abi: Align(1 bytes), - pref: $PREF_ALIGN, + variants: Single { + index: 1, }, - size: Size(2 bytes), }, ], }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size(0 bytes), - value: Int( - I16, - false, - ), - valid_range: 0..=1, - }, - ), - align: AbiAndPrefAlign { - abi: Align(4 bytes), - pref: $PREF_ALIGN, - }, - size: Size(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:44:1 | diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr index ce22eca1b8c..e021f500c66 100644 --- a/src/test/ui/lint/unreachable_pub.stderr +++ b/src/test/ui/lint/unreachable_pub.stderr @@ -1,8 +1,8 @@ warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:8:5 + --> $DIR/unreachable_pub.rs:8:13 | LL | pub use std::fmt; - | ---^^^^^^^^^^^^^^ + | --- ^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | @@ -93,7 +93,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:33:5 | LL | pub const CARBON: usize = 1; - | ---^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---^^^^^^^^^^^^^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | @@ -103,7 +103,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:34:5 | LL | pub static NITROGEN: usize = 2; - | ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---^^^^^^^^^^^^^^^^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | @@ -113,7 +113,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:35:5 | LL | pub type Oxygen = bool; - | ---^^^^^^^^^^^^^^^^^^^^ + | ---^^^^^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | @@ -123,7 +123,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:38:47 | LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_empty_struct_with_visibility!(pub, Fluorine); | --------------------------------------------------- @@ -138,7 +138,7 @@ warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:44:9 | LL | pub fn catalyze() -> bool; - | ---^^^^^^^^^^^^^^^^^^^^^^^ + | ---^^^^^^^^^^^^^^^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | diff --git a/src/test/ui/moves/issue-99470-move-out-of-some.rs b/src/test/ui/moves/issue-99470-move-out-of-some.rs new file mode 100644 index 00000000000..f404cd3cd71 --- /dev/null +++ b/src/test/ui/moves/issue-99470-move-out-of-some.rs @@ -0,0 +1,9 @@ +fn main() { + let x: &Option<Box<i32>> = &Some(Box::new(0)); + + match x { + //~^ ERROR cannot move out of `x` as enum variant `Some` which is behind a shared reference + &Some(_y) => (), + &None => (), + } +} diff --git a/src/test/ui/moves/issue-99470-move-out-of-some.stderr b/src/test/ui/moves/issue-99470-move-out-of-some.stderr new file mode 100644 index 00000000000..6e4a4e5ba22 --- /dev/null +++ b/src/test/ui/moves/issue-99470-move-out-of-some.stderr @@ -0,0 +1,16 @@ +error[E0507]: cannot move out of `x` as enum variant `Some` which is behind a shared reference + --> $DIR/issue-99470-move-out-of-some.rs:4:11 + | +LL | match x { + | ^ +LL | +LL | &Some(_y) => (), + | --------- + | | | + | | data moved here + | | move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Some(_y)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.stderr b/src/test/ui/moves/moves-based-on-type-block-bad.stderr index a9ac9d63a95..5ed91a0d559 100644 --- a/src/test/ui/moves/moves-based-on-type-block-bad.stderr +++ b/src/test/ui/moves/moves-based-on-type-block-bad.stderr @@ -1,4 +1,4 @@ -error[E0507]: cannot move out of `hellothere.x.0` which is behind a shared reference +error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is behind a shared reference --> $DIR/moves-based-on-type-block-bad.rs:22:19 | LL | match hellothere.x { diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr index 0df326425ad..b03fcf70bab 100644 --- a/src/test/ui/nll/move-errors.stderr +++ b/src/test/ui/nll/move-errors.stderr @@ -45,7 +45,7 @@ LL | let a = [A("".to_string())][0]; | move occurs because value has type `A`, which does not implement the `Copy` trait | help: consider borrowing here: `&[A("".to_string())][0]` -error[E0507]: cannot move out of `a.0` which is behind a shared reference +error[E0507]: cannot move out of `a` which is behind a shared reference --> $DIR/move-errors.rs:38:16 | LL | let A(s) = *a; @@ -134,7 +134,7 @@ LL | F(s, mut t) => (), | = note: move occurs because these variables have types that don't implement the `Copy` trait -error[E0507]: cannot move out of `x.0` which is behind a shared reference +error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference --> $DIR/move-errors.rs:110:11 | LL | match *x { diff --git a/src/test/ui/panics/location-detail-panic-no-location-info.rs b/src/test/ui/panics/location-detail-panic-no-location-info.rs new file mode 100644 index 00000000000..7b609145bad --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-location-info.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=none +// exec-env:RUST_BACKTRACE=0 + +fn main() { + panic!("no location info"); +} diff --git a/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr b/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr new file mode 100644 index 00000000000..d1c3108643c --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-location-info.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'no location info', <redacted>:0:0 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui-fulldeps/auxiliary/proc-macro-panic.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs index fc15bb9c59d..fc15bb9c59d 100644 --- a/src/test/ui-fulldeps/auxiliary/proc-macro-panic.rs +++ b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index fdf3ca2e261..814cd77cfe9 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -1,9 +1,4 @@ // aux-build:invalid-punct-ident.rs -// ignore-stage1 -// only-linux -// -// FIXME: This should be a normal (stage1, all platforms) test in -// src/test/ui/proc-macro once issue #59998 is fixed. #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr index bb0a48cb16b..7babe685bed 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-1.rs:11:1 + --> $DIR/invalid-punct-ident-1.rs:6:1 | LL | invalid_punct!(); | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 151f6203439..a04dec707fe 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -1,9 +1,4 @@ // aux-build:invalid-punct-ident.rs -// ignore-stage1 -// only-linux -// -// FIXME: This should be a normal (stage1, all platforms) test in -// src/test/ui/proc-macro once issue #59998 is fixed. #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr index 0bd07bd649e..01b80768c57 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-2.rs:11:1 + --> $DIR/invalid-punct-ident-2.rs:6:1 | LL | invalid_ident!(); | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index 7c22a56b6fb..f0e953608cb 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -1,9 +1,4 @@ // aux-build:invalid-punct-ident.rs -// ignore-stage1 -// only-linux -// -// FIXME: This should be a normal (stage1, all platforms) test in -// src/test/ui/proc-macro once issue #59998 is fixed. #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr index a0cc5ef6e2d..899c38158c2 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-3.rs:11:1 + --> $DIR/invalid-punct-ident-3.rs:6:1 | LL | invalid_raw_ident!(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.rs b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs index 981abb4e2c4..98fa06b6e45 100644 --- a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.rs +++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs @@ -1,10 +1,5 @@ // aux-build:proc-macro-panic.rs // edition:2018 -// ignore-stage1 -// only-linux -// -// FIXME: This should be a normal (stage1, all platforms) test in -// src/test/ui/proc-macro once issue #59998 is fixed. // Regression test for issue #76270 // Tests that we don't print an ICE message when a panic diff --git a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr index 5cc292dbb40..1dc0f16bf6c 100644 --- a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr +++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/issue-76270-panic-in-libproc-macro.rs:15:1 + --> $DIR/issue-76270-panic-in-libproc-macro.rs:10:1 | LL | proc_macro_panic::panic_in_libproc_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/load-panic-backtrace.rs b/src/test/ui/proc-macro/load-panic-backtrace.rs index 4a3ba9aee74..cd6f70a5575 100644 --- a/src/test/ui/proc-macro/load-panic-backtrace.rs +++ b/src/test/ui/proc-macro/load-panic-backtrace.rs @@ -1,18 +1,8 @@ // aux-build:test-macros.rs // compile-flags: -Z proc-macro-backtrace // rustc-env:RUST_BACKTRACE=0 - -// FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread '.*' panicked " -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" -// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" -// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" -// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" -// normalize-stderr-test "note: compiler flags.*\n\n" -> "" -// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" -// normalize-stderr-test "query stack during panic:\n" -> "" -// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> "" -// normalize-stderr-test "end of query stack\n" -> "" #[macro_use] extern crate test_macros; diff --git a/src/test/ui/proc-macro/load-panic-backtrace.stderr b/src/test/ui/proc-macro/load-panic-backtrace.stderr index f825047e331..cef5786d1b8 100644 --- a/src/test/ui/proc-macro/load-panic-backtrace.stderr +++ b/src/test/ui/proc-macro/load-panic-backtrace.stderr @@ -1,6 +1,6 @@ at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5 error: proc-macro derive panicked - --> $DIR/load-panic-backtrace.rs:20:10 + --> $DIR/load-panic-backtrace.rs:10:10 | LL | #[derive(Panic)] | ^^^^^ diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index f839bd42432..20aeb7b995a 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -8,8 +8,14 @@ LL | impl dyn ToNbt<Self> {} note: cycle used when collecting item types in top-level module --> $DIR/issue-23305.rs:1:1 | -LL | pub trait ToNbt<T> { - | ^^^^^^^^^^^^^^^^^^ +LL | / pub trait ToNbt<T> { +LL | | fn new(val: T) -> Self; +LL | | } +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs index 689fdcebbfb..0fe50932b4b 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs @@ -32,6 +32,8 @@ fn _if_let_guard() { () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} //~^ ERROR `if let` guards are experimental //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement () if let Range { start: _, end: _ } = (true..true) && false => {} //~^ ERROR `if let` guards are experimental diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr index b61041050a8..35db84a6cb7 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr @@ -41,19 +41,31 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:52:16 + --> $DIR/feature-gate.rs:32:55 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:32:68 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:54:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:54:16 + --> $DIR/feature-gate.rs:56:16 | LL | use_expr!((let 0 = 1)); | ^^^ error: no rules expected the token `let` - --> $DIR/feature-gate.rs:62:15 + --> $DIR/feature-gate.rs:64:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -102,7 +114,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:36:12 + --> $DIR/feature-gate.rs:38:12 | LL | () if let Range { start: _, end: _ } = (true..true) && false => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +124,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:58:12 + --> $DIR/feature-gate.rs:60:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -121,6 +133,6 @@ LL | () if let 0 = 1 => {} = help: add `#![feature(if_let_guard)]` to the crate attributes to enable = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>` -error: aborting due to 16 previous errors +error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index a89c58785e3..e8f1ff9c3fd 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -51,6 +51,8 @@ fn _if() { //~| ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement } fn _while() { @@ -81,6 +83,8 @@ fn _while() { //~| ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement } fn _macros() { @@ -146,6 +150,7 @@ fn nested_within_if_expr() { //~| ERROR expected expression, found `let` statement if true || (true && let 0 = 0) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement let mut x = true; if x = let 0 = 0 {} @@ -237,6 +242,7 @@ fn nested_within_while_expr() { //~| ERROR expected expression, found `let` statement while true || (true && let 0 = 0) {} //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement let mut x = true; while x = let 0 = 0 {} @@ -388,16 +394,19 @@ fn inside_const_generic_arguments() { if let A::<{ true && let 1 = 1 //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement }>::O = 5 {} while let A::<{ true && let 1 = 1 //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement }>::O = 5 {} if A::<{ true && let 1 = 1 //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement }>::O == 5 {} // In the cases above we have `ExprKind::Block` to help us out. @@ -409,7 +418,8 @@ fn inside_const_generic_arguments() { if A::< true && let 1 = 1 //~^ ERROR `let` expressions are not supported here - //~| ERROR expressions must be enclosed in braces + //~| ERROR expressions must be enclosed in braces + //~| ERROR expected expression, found `let` statement >::O == 5 {} } diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 5e5289f1693..d5d82166a4a 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -41,313 +41,373 @@ LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:57:12 + --> $DIR/disallowed-positions.rs:49:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:49:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:63:14 | LL | while (((let 0 = 1))) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:67:12 | LL | while (let 0 = 1) && true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:69:20 + --> $DIR/disallowed-positions.rs:71:20 | LL | while true && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:73:12 + --> $DIR/disallowed-positions.rs:75:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:73:27 + --> $DIR/disallowed-positions.rs:75:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:79:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 + --> $DIR/disallowed-positions.rs:81:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:81:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:114:9 | LL | if &let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:115:9 + --> $DIR/disallowed-positions.rs:119:9 | LL | if !let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:9 + --> $DIR/disallowed-positions.rs:122:9 | LL | if *let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:9 + --> $DIR/disallowed-positions.rs:126:9 | LL | if -let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:132:9 + --> $DIR/disallowed-positions.rs:136:9 | LL | if (let 0 = 0)? {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:16 + --> $DIR/disallowed-positions.rs:142:16 | LL | if true || let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:141:17 + --> $DIR/disallowed-positions.rs:145:17 | LL | if (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:144:25 + --> $DIR/disallowed-positions.rs:148:25 | LL | if true && (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:151:12 + --> $DIR/disallowed-positions.rs:151:25 + | +LL | if true || (true && let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:156:12 | LL | if x = let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:156:15 + --> $DIR/disallowed-positions.rs:161:15 | LL | if true..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:160:11 + --> $DIR/disallowed-positions.rs:165:11 | LL | if ..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:9 + --> $DIR/disallowed-positions.rs:169:9 | LL | if (let 0 = 0).. {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:19 + --> $DIR/disallowed-positions.rs:200:19 | LL | if let true = let true = true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:201:12 + --> $DIR/disallowed-positions.rs:206:12 | LL | while &let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:206:12 + --> $DIR/disallowed-positions.rs:211:12 | LL | while !let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:12 + --> $DIR/disallowed-positions.rs:214:12 | LL | while *let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:213:12 + --> $DIR/disallowed-positions.rs:218:12 | LL | while -let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:223:12 + --> $DIR/disallowed-positions.rs:228:12 | LL | while (let 0 = 0)? {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:229:19 + --> $DIR/disallowed-positions.rs:234:19 | LL | while true || let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:232:20 + --> $DIR/disallowed-positions.rs:237:20 | LL | while (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:235:28 + --> $DIR/disallowed-positions.rs:240:28 | LL | while true && (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:242:15 + --> $DIR/disallowed-positions.rs:243:28 + | +LL | while true || (true && let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:248:15 | LL | while x = let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:247:18 + --> $DIR/disallowed-positions.rs:253:18 | LL | while true..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:251:14 + --> $DIR/disallowed-positions.rs:257:14 | LL | while ..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:12 + --> $DIR/disallowed-positions.rs:261:12 | LL | while (let 0 = 0).. {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:286:22 + --> $DIR/disallowed-positions.rs:292:22 | LL | while let true = let true = true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:302:6 + --> $DIR/disallowed-positions.rs:308:6 | LL | &let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:306:6 + --> $DIR/disallowed-positions.rs:312:6 | LL | !let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:315:6 | LL | *let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:313:6 + --> $DIR/disallowed-positions.rs:319:6 | LL | -let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:6 + --> $DIR/disallowed-positions.rs:329:6 | LL | (let 0 = 0)?; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:329:13 + --> $DIR/disallowed-positions.rs:335:13 | LL | true || let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:332:14 + --> $DIR/disallowed-positions.rs:338:14 | LL | (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:335:22 + --> $DIR/disallowed-positions.rs:341:22 | LL | true && (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:346:9 | LL | x = let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:12 + --> $DIR/disallowed-positions.rs:350:12 | LL | true..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:8 + --> $DIR/disallowed-positions.rs:353:8 | LL | ..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:350:6 + --> $DIR/disallowed-positions.rs:356:6 | LL | (let 0 = 0)..; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:354:6 + --> $DIR/disallowed-positions.rs:360:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:6 + --> $DIR/disallowed-positions.rs:365:6 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:17 + --> $DIR/disallowed-positions.rs:365:17 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:366:25 + --> $DIR/disallowed-positions.rs:372:25 | LL | let x = true && let y = 1; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:19 + --> $DIR/disallowed-positions.rs:378:19 | LL | [1, 2, 3][let _ = ()] | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:377:6 + --> $DIR/disallowed-positions.rs:383:6 | LL | &let 0 = 0 | ^^^ +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:395:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:401:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:407:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:419:17 + | +LL | true && let 1 = 1 + | ^^^ + error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:410:9 + --> $DIR/disallowed-positions.rs:419:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -358,97 +418,97 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:419:9 + --> $DIR/disallowed-positions.rs:429:9 | LL | if (let Some(a) = opt && true) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:424:9 + --> $DIR/disallowed-positions.rs:434:9 | LL | if (let Some(a) = opt) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:428:9 + --> $DIR/disallowed-positions.rs:438:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:428:32 + --> $DIR/disallowed-positions.rs:438:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:437:9 + --> $DIR/disallowed-positions.rs:447:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:437:31 + --> $DIR/disallowed-positions.rs:447:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:443:9 + --> $DIR/disallowed-positions.rs:453:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:443:31 + --> $DIR/disallowed-positions.rs:453:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:449:9 + --> $DIR/disallowed-positions.rs:459:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:466:22 + --> $DIR/disallowed-positions.rs:476:22 | LL | let x = (true && let y = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:471:20 + --> $DIR/disallowed-positions.rs:481:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:475:20 + --> $DIR/disallowed-positions.rs:485:20 | LL | #[cfg(FALSE)] (let 0 = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:97:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:101:16 | LL | use_expr!((let 0 = 1)); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:101:23 + --> $DIR/disallowed-positions.rs:105:23 | LL | use_expr!(true && let 0 = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:105:17 + --> $DIR/disallowed-positions.rs:109:17 | LL | noop_expr!((let 0 = 1)); | ^^^ @@ -571,176 +631,176 @@ LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:57:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:57:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:63:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:63:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:67:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:12 + --> $DIR/disallowed-positions.rs:67:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:69:20 + --> $DIR/disallowed-positions.rs:71:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:69:20 + --> $DIR/disallowed-positions.rs:71:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:73:12 + --> $DIR/disallowed-positions.rs:75:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:73:12 + --> $DIR/disallowed-positions.rs:75:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:73:27 + --> $DIR/disallowed-positions.rs:75:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:73:27 + --> $DIR/disallowed-positions.rs:75:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:79:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:79:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:79:51 + --> $DIR/disallowed-positions.rs:81:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:79:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:79:64 + --> $DIR/disallowed-positions.rs:81:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:79:38 + --> $DIR/disallowed-positions.rs:81:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:97:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:97:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:97:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:97:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:101:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:101:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:101:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:101:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:110:9 + --> $DIR/disallowed-positions.rs:114:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -748,7 +808,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:115:9 + --> $DIR/disallowed-positions.rs:119:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -756,7 +816,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:118:9 + --> $DIR/disallowed-positions.rs:122:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -764,7 +824,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:122:9 + --> $DIR/disallowed-positions.rs:126:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -772,72 +832,72 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:132:9 + --> $DIR/disallowed-positions.rs:136:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:132:9 + --> $DIR/disallowed-positions.rs:136:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:138:16 + --> $DIR/disallowed-positions.rs:142:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:138:13 + --> $DIR/disallowed-positions.rs:142:13 | LL | if true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:141:17 + --> $DIR/disallowed-positions.rs:145:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:141:14 + --> $DIR/disallowed-positions.rs:145:14 | LL | if (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:144:25 + --> $DIR/disallowed-positions.rs:148:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:144:22 + --> $DIR/disallowed-positions.rs:148:22 | LL | if true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:147:25 + --> $DIR/disallowed-positions.rs:151:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:147:17 + --> $DIR/disallowed-positions.rs:151:17 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:151:12 + --> $DIR/disallowed-positions.rs:156:12 | LL | if x = let 0 = 0 {} | ^^^^^^^^^ @@ -845,46 +905,46 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:156:15 + --> $DIR/disallowed-positions.rs:161:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:156:15 + --> $DIR/disallowed-positions.rs:161:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:160:11 + --> $DIR/disallowed-positions.rs:165:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:160:11 + --> $DIR/disallowed-positions.rs:165:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:164:9 + --> $DIR/disallowed-positions.rs:169:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:164:9 + --> $DIR/disallowed-positions.rs:169:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:170:8 + --> $DIR/disallowed-positions.rs:175:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -892,7 +952,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:174:8 + --> $DIR/disallowed-positions.rs:179:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -900,7 +960,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:181:8 + --> $DIR/disallowed-positions.rs:186:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -908,7 +968,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:189:8 + --> $DIR/disallowed-positions.rs:194:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -916,7 +976,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:195:19 + --> $DIR/disallowed-positions.rs:200:19 | LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -924,7 +984,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:201:12 + --> $DIR/disallowed-positions.rs:206:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -932,7 +992,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:206:12 + --> $DIR/disallowed-positions.rs:211:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -940,7 +1000,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:209:12 + --> $DIR/disallowed-positions.rs:214:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -948,7 +1008,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:213:12 + --> $DIR/disallowed-positions.rs:218:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -956,72 +1016,72 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:223:12 + --> $DIR/disallowed-positions.rs:228:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:223:12 + --> $DIR/disallowed-positions.rs:228:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:229:19 + --> $DIR/disallowed-positions.rs:234:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:229:16 + --> $DIR/disallowed-positions.rs:234:16 | LL | while true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:232:20 + --> $DIR/disallowed-positions.rs:237:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:232:17 + --> $DIR/disallowed-positions.rs:237:17 | LL | while (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:235:28 + --> $DIR/disallowed-positions.rs:240:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:235:25 + --> $DIR/disallowed-positions.rs:240:25 | LL | while true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:238:28 + --> $DIR/disallowed-positions.rs:243:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:238:20 + --> $DIR/disallowed-positions.rs:243:20 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:242:15 + --> $DIR/disallowed-positions.rs:248:15 | LL | while x = let 0 = 0 {} | ^^^^^^^^^ @@ -1029,46 +1089,46 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:247:18 + --> $DIR/disallowed-positions.rs:253:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:247:18 + --> $DIR/disallowed-positions.rs:253:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:251:14 + --> $DIR/disallowed-positions.rs:257:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:251:14 + --> $DIR/disallowed-positions.rs:257:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:255:12 + --> $DIR/disallowed-positions.rs:261:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:255:12 + --> $DIR/disallowed-positions.rs:261:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:261:11 + --> $DIR/disallowed-positions.rs:267:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1076,7 +1136,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:265:11 + --> $DIR/disallowed-positions.rs:271:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1084,7 +1144,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:272:11 + --> $DIR/disallowed-positions.rs:278:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1092,7 +1152,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:280:11 + --> $DIR/disallowed-positions.rs:286:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1100,7 +1160,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:286:22 + --> $DIR/disallowed-positions.rs:292:22 | LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -1108,7 +1168,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:302:6 + --> $DIR/disallowed-positions.rs:308:6 | LL | &let 0 = 0; | ^^^^^^^^^ @@ -1116,7 +1176,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:306:6 + --> $DIR/disallowed-positions.rs:312:6 | LL | !let 0 = 0; | ^^^^^^^^^ @@ -1124,7 +1184,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:315:6 | LL | *let 0 = 0; | ^^^^^^^^^ @@ -1132,7 +1192,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:313:6 + --> $DIR/disallowed-positions.rs:319:6 | LL | -let 0 = 0; | ^^^^^^^^^ @@ -1140,59 +1200,59 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:323:6 + --> $DIR/disallowed-positions.rs:329:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:323:6 + --> $DIR/disallowed-positions.rs:329:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:329:13 + --> $DIR/disallowed-positions.rs:335:13 | LL | true || let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:329:10 + --> $DIR/disallowed-positions.rs:335:10 | LL | true || let 0 = 0; | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:332:14 + --> $DIR/disallowed-positions.rs:338:14 | LL | (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:332:11 + --> $DIR/disallowed-positions.rs:338:11 | LL | (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:335:22 + --> $DIR/disallowed-positions.rs:341:22 | LL | true && (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:335:19 + --> $DIR/disallowed-positions.rs:341:19 | LL | true && (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:346:9 | LL | x = let 0 = 0; | ^^^^^^^^^ @@ -1200,46 +1260,46 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:344:12 + --> $DIR/disallowed-positions.rs:350:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:12 + --> $DIR/disallowed-positions.rs:350:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:347:8 + --> $DIR/disallowed-positions.rs:353:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:8 + --> $DIR/disallowed-positions.rs:353:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:350:6 + --> $DIR/disallowed-positions.rs:356:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:350:6 + --> $DIR/disallowed-positions.rs:356:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:354:6 + --> $DIR/disallowed-positions.rs:360:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1247,20 +1307,20 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:359:6 + --> $DIR/disallowed-positions.rs:365:6 | LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:6 + --> $DIR/disallowed-positions.rs:365:6 | LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:377:6 + --> $DIR/disallowed-positions.rs:383:6 | LL | &let 0 = 0 | ^^^^^^^^^ @@ -1268,7 +1328,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:389:17 + --> $DIR/disallowed-positions.rs:395:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1276,7 +1336,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:394:17 + --> $DIR/disallowed-positions.rs:401:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1284,7 +1344,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:399:17 + --> $DIR/disallowed-positions.rs:407:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1292,7 +1352,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:410:17 + --> $DIR/disallowed-positions.rs:419:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1300,124 +1360,124 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:419:9 + --> $DIR/disallowed-positions.rs:429:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:419:9 + --> $DIR/disallowed-positions.rs:429:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:424:9 + --> $DIR/disallowed-positions.rs:434:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:424:9 + --> $DIR/disallowed-positions.rs:434:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:428:9 + --> $DIR/disallowed-positions.rs:438:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:428:9 + --> $DIR/disallowed-positions.rs:438:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:428:32 + --> $DIR/disallowed-positions.rs:438:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:428:32 + --> $DIR/disallowed-positions.rs:438:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:437:9 + --> $DIR/disallowed-positions.rs:447:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:437:9 + --> $DIR/disallowed-positions.rs:447:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:437:31 + --> $DIR/disallowed-positions.rs:447:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:437:31 + --> $DIR/disallowed-positions.rs:447:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:443:9 + --> $DIR/disallowed-positions.rs:453:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:443:9 + --> $DIR/disallowed-positions.rs:453:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:443:31 + --> $DIR/disallowed-positions.rs:453:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:443:31 + --> $DIR/disallowed-positions.rs:453:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:449:9 + --> $DIR/disallowed-positions.rs:459:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:449:9 + --> $DIR/disallowed-positions.rs:459:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:110:8 + --> $DIR/disallowed-positions.rs:114:8 | LL | if &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1429,19 +1489,19 @@ LL + if let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:118:8 + --> $DIR/disallowed-positions.rs:122:8 | LL | if *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:122:8 + --> $DIR/disallowed-positions.rs:126:8 | LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:132:8 + --> $DIR/disallowed-positions.rs:136:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1449,7 +1509,7 @@ LL | if (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:132:19 + --> $DIR/disallowed-positions.rs:136:19 | LL | / fn nested_within_if_expr() { LL | | if &let 0 = 0 {} @@ -1466,7 +1526,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:151:8 + --> $DIR/disallowed-positions.rs:156:8 | LL | if x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1477,7 +1537,7 @@ LL | if x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:156:8 + --> $DIR/disallowed-positions.rs:161:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1486,7 +1546,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:160:8 + --> $DIR/disallowed-positions.rs:165:8 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1495,7 +1555,7 @@ LL | if ..(let 0 = 0) {} found struct `RangeTo<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:164:8 + --> $DIR/disallowed-positions.rs:169:8 | LL | if (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1504,7 +1564,7 @@ LL | if (let 0 = 0).. {} found struct `RangeFrom<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:170:12 + --> $DIR/disallowed-positions.rs:175:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1515,7 +1575,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:170:8 + --> $DIR/disallowed-positions.rs:175:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1524,7 +1584,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:174:12 + --> $DIR/disallowed-positions.rs:179:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1535,7 +1595,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:174:8 + --> $DIR/disallowed-positions.rs:179:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1544,7 +1604,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:186:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1555,20 +1615,20 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:181:41 + --> $DIR/disallowed-positions.rs:186:41 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:181:41: 181:43]` + found closure `[closure@$DIR/disallowed-positions.rs:186:41: 186:43]` help: use parentheses to call this closure | LL | if let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:181:8 + --> $DIR/disallowed-positions.rs:186:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1577,7 +1637,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:189:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1588,7 +1648,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:189:44 + --> $DIR/disallowed-positions.rs:194:44 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1600,7 +1660,7 @@ LL + if let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:189:8 + --> $DIR/disallowed-positions.rs:194:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1609,7 +1669,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<bool>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:128:20 + --> $DIR/disallowed-positions.rs:132:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1617,7 +1677,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:201:11 + --> $DIR/disallowed-positions.rs:206:11 | LL | while &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1629,19 +1689,19 @@ LL + while let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:209:11 + --> $DIR/disallowed-positions.rs:214:11 | LL | while *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:213:11 + --> $DIR/disallowed-positions.rs:218:11 | LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:223:11 + --> $DIR/disallowed-positions.rs:228:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1649,7 +1709,7 @@ LL | while (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:223:22 + --> $DIR/disallowed-positions.rs:228:22 | LL | / fn nested_within_while_expr() { LL | | while &let 0 = 0 {} @@ -1666,7 +1726,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:242:11 + --> $DIR/disallowed-positions.rs:248:11 | LL | while x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1677,7 +1737,7 @@ LL | while x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:247:11 + --> $DIR/disallowed-positions.rs:253:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1686,7 +1746,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:251:11 + --> $DIR/disallowed-positions.rs:257:11 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1695,7 +1755,7 @@ LL | while ..(let 0 = 0) {} found struct `RangeTo<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:255:11 + --> $DIR/disallowed-positions.rs:261:11 | LL | while (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1704,7 +1764,7 @@ LL | while (let 0 = 0).. {} found struct `RangeFrom<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:261:15 + --> $DIR/disallowed-positions.rs:267:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1715,7 +1775,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:261:11 + --> $DIR/disallowed-positions.rs:267:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1724,7 +1784,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:265:15 + --> $DIR/disallowed-positions.rs:271:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1735,7 +1795,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:265:11 + --> $DIR/disallowed-positions.rs:271:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1744,7 +1804,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:278:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1755,20 +1815,20 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:272:44 + --> $DIR/disallowed-positions.rs:278:44 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:272:44: 272:46]` + found closure `[closure@$DIR/disallowed-positions.rs:278:44: 278:46]` help: use parentheses to call this closure | LL | while let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:272:11 + --> $DIR/disallowed-positions.rs:278:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1777,7 +1837,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<bool>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:280:15 + --> $DIR/disallowed-positions.rs:286:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1788,7 +1848,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:280:47 + --> $DIR/disallowed-positions.rs:286:47 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1800,7 +1860,7 @@ LL + while let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:280:11 + --> $DIR/disallowed-positions.rs:286:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1809,7 +1869,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<bool>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:219:23 + --> $DIR/disallowed-positions.rs:224:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1817,19 +1877,19 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:309:5 + --> $DIR/disallowed-positions.rs:315:5 | LL | *let 0 = 0; | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:313:5 + --> $DIR/disallowed-positions.rs:319:5 | LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:323:5 + --> $DIR/disallowed-positions.rs:329:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1837,7 +1897,7 @@ LL | (let 0 = 0)?; = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:323:16 + --> $DIR/disallowed-positions.rs:329:16 | LL | / fn outside_if_and_while_expr() { LL | | &let 0 = 0; @@ -1854,7 +1914,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:354:10 + --> $DIR/disallowed-positions.rs:360:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1865,7 +1925,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:377:5 + --> $DIR/disallowed-positions.rs:383:5 | LL | fn outside_if_and_while_expr() { | - help: try adding a return type: `-> &bool` @@ -1874,14 +1934,14 @@ LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:319:17 + --> $DIR/disallowed-positions.rs:325:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 208 previous errors +error: aborting due to 218 previous errors Some errors have detailed explanations: E0277, E0308, E0600, E0614. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr index ca09c3d5ff1..e5443290f9e 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr @@ -1,4 +1,4 @@ -error[E0507]: cannot move out of `s.0` which is behind a shared reference +error[E0507]: cannot move out of `s` which is behind a shared reference --> $DIR/simple.rs:38:17 | LL | let X(_t) = *s; @@ -7,7 +7,7 @@ LL | let X(_t) = *s; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:42:30 | LL | if let Either::One(_t) = *r { } @@ -16,7 +16,7 @@ LL | if let Either::One(_t) = *r { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:46:33 | LL | while let Either::One(_t) = *r { } @@ -25,7 +25,7 @@ LL | while let Either::One(_t) = *r { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference --> $DIR/simple.rs:50:11 | LL | match *r { @@ -37,7 +37,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:57:11 | LL | match *r { @@ -49,7 +49,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `sm.0` which is behind a mutable reference +error[E0507]: cannot move out of `sm` which is behind a mutable reference --> $DIR/simple.rs:66:17 | LL | let X(_t) = *sm; @@ -58,7 +58,7 @@ LL | let X(_t) = *sm; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:70:30 | LL | if let Either::One(_t) = *rm { } @@ -67,7 +67,7 @@ LL | if let Either::One(_t) = *rm { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:74:33 | LL | while let Either::One(_t) = *rm { } @@ -76,7 +76,7 @@ LL | while let Either::One(_t) = *rm { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference --> $DIR/simple.rs:78:11 | LL | match *rm { @@ -88,7 +88,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:85:11 | LL | match *rm { @@ -100,7 +100,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:93:11 | LL | match *rm { @@ -226,7 +226,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -error[E0507]: cannot move out of `s.0` which is behind a shared reference +error[E0507]: cannot move out of `s` which is behind a shared reference --> $DIR/simple.rs:168:18 | LL | let &X(_t) = s; @@ -236,7 +236,7 @@ LL | let &X(_t) = s; | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the `&`: `X(_t)` -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:172:31 | LL | if let &Either::One(_t) = r { } @@ -246,7 +246,7 @@ LL | if let &Either::One(_t) = r { } | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&`: `Either::One(_t)` -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:176:34 | LL | while let &Either::One(_t) = r { } @@ -256,7 +256,7 @@ LL | while let &Either::One(_t) = r { } | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&`: `Either::One(_t)` -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference --> $DIR/simple.rs:180:11 | LL | match r { @@ -276,7 +276,7 @@ LL + LL ~ | &Either::Two(_t) => (), | -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:188:11 | LL | match r { @@ -289,7 +289,7 @@ LL | &Either::One(_t) => (), | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&`: `Either::One(_t)` -error[E0507]: cannot move out of `r.0` which is behind a shared reference +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference --> $DIR/simple.rs:195:11 | LL | match r { @@ -302,7 +302,7 @@ LL | &Either::One(_t) => (), | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&`: `Either::One(_t)` -error[E0507]: cannot move out of `sm.0` which is behind a mutable reference +error[E0507]: cannot move out of `sm` which is behind a mutable reference --> $DIR/simple.rs:207:22 | LL | let &mut X(_t) = sm; @@ -312,7 +312,7 @@ LL | let &mut X(_t) = sm; | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the `&mut`: `X(_t)` -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:211:35 | LL | if let &mut Either::One(_t) = rm { } @@ -322,7 +322,7 @@ LL | if let &mut Either::One(_t) = rm { } | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&mut`: `Either::One(_t)` -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:215:38 | LL | while let &mut Either::One(_t) = rm { } @@ -332,7 +332,7 @@ LL | while let &mut Either::One(_t) = rm { } | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&mut`: `Either::One(_t)` -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference --> $DIR/simple.rs:219:11 | LL | match rm { @@ -354,7 +354,7 @@ help: consider removing the `&mut` LL | Either::Two(_t) => (), | ~~~~~~~~~~~~~~~ -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:228:11 | LL | match rm { @@ -367,7 +367,7 @@ LL | &mut Either::One(_t) => (), | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&mut`: `Either::One(_t)` -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:235:11 | LL | match rm { @@ -380,7 +380,7 @@ LL | &mut Either::One(_t) => (), | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the `&mut`: `Either::One(_t)` -error[E0507]: cannot move out of `rm.0` which is behind a mutable reference +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference --> $DIR/simple.rs:242:11 | LL | match rm { diff --git a/src/test/ui/suggestions/if-then-neeing-semi.rs b/src/test/ui/suggestions/if-then-neeing-semi.rs new file mode 100644 index 00000000000..b487f013d27 --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.rs @@ -0,0 +1,70 @@ +// edition:2018 + +fn dummy() -> i32 { + 42 +} + +fn extra_semicolon() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy() //~ NOTE expected because of this + //~| HELP consider `await`ing on both `Future`s + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future<Output = ()>` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/if-then-neeing-semi.stderr b/src/test/ui/suggestions/if-then-neeing-semi.stderr new file mode 100644 index 00000000000..d7c5818abbd --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.stderr @@ -0,0 +1,130 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:37:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy() + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy().await + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:50:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy2().await + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } else { +LL ~ Box::new(async_dummy2()) + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:63:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy() + | | ------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ async_dummy().await +LL | +LL | } else { +LL ~ async_dummy2().await + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | +LL | | } else { +LL | | dummy() + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed new file mode 100644 index 00000000000..691e7553a09 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>); + +impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {} + +impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs new file mode 100644 index 00000000000..e3185e7eff8 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>); + +impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {} + +impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr new file mode 100644 index 00000000000..e0f405eedfa --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -0,0 +1,22 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9 + | +LL | struct Wrapper<T>(T); + | - this field does not implement `Copy` +... +LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} + | ^^^^ + | +note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display` + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + | +LL | struct Wrapper<T>(T); + | ^ +help: consider restricting type parameter `S` + | +LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed new file mode 100644 index 00000000000..32a7215c5bd --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +impl<S: Copy> Copy for Wrapper<S> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs new file mode 100644 index 00000000000..c688f4d41ee --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +impl<S> Copy for Wrapper<S> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr new file mode 100644 index 00000000000..218988511db --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -0,0 +1,17 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl.rs:6:9 + | +LL | struct Wrapper<T>(T); + | - this field does not implement `Copy` +LL | +LL | impl<S> Copy for Wrapper<S> {} + | ^^^^ + | +help: consider restricting type parameter `S` + | +LL | impl<S: Copy> Copy for Wrapper<S> {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr index 86dbd0aac03..f5d6d72afc2 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -4,11 +4,10 @@ warning: function cannot return without recursing LL | / fn recurse<T>(elements: T) -> Vec<char> LL | | where LL | | T: Iterator<Item = ()>, -LL | | { -LL | | recurse(IteratorOfWrapped(elements).map(|t| t.0)) - | | ------------------------------------------------- recursive call site -LL | | } - | |_^ cannot return without recursing + | |___________________________^ cannot return without recursing +LL | { +LL | recurse(IteratorOfWrapped(elements).map(|t| t.0)) + | ------------------------------------------------- recursive call site | = note: `#[warn(unconditional_recursion)]` on by default = help: a `loop` may express intention better if this is on purpose diff --git a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr index ac005725ab4..15faab16abe 100644 --- a/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr +++ b/src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -14,7 +14,7 @@ note: cycle used when collecting item types in top-level module --> $DIR/cyclic-trait-resolution.rs:1:1 | LL | trait A: B + A {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 277f4e84240..4775e68820b 100644 --- a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -2,18 +2,18 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph --> $DIR/self-in-enum-definition.rs:5:10 | LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 | LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 | LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Alpha`... = note: ...which again requires simplifying constant for the type system `Alpha::V3::{constant#0}`, completing the cycle note: cycle used when collecting item types in top-level module diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 80c84014bfd..4f9ff97f1fd 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -220,9 +220,11 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tc } fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: DefId) -> String { - match cx.tcx.associated_item(method_def_id).container { - ty::TraitContainer(def_id) => cx.tcx.def_path_str(def_id), - ty::ImplContainer(def_id) => { + let assoc_item = cx.tcx.associated_item(method_def_id); + let def_id = assoc_item.container_id(cx.tcx); + match assoc_item.container { + ty::TraitContainer => cx.tcx.def_path_str(def_id), + ty::ImplContainer => { let ty = cx.tcx.type_of(def_id); match ty.kind() { ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()), diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index b638f271602..e9e13aece18 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1112,7 +1112,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { let mut pos = 0usize; let mut iter = tokenize(&snip).map(|t| { let start = pos; - pos += t.len; + pos += t.len as usize; (t.kind, start..pos) }); diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index a20377f320b..88ba002927a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -10,7 +10,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{self, DefIdTree}; +use rustc_middle::ty::DefIdTree; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Span; @@ -153,13 +153,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. - match cx.tcx.associated_item(impl_item.def_id).container { - ty::TraitContainer(_) => return, - ty::ImplContainer(cid) => { - if cx.tcx.impl_trait_ref(cid).is_some() { - return; - } - }, + if let Some(cid) = cx.tcx.associated_item(impl_item.def_id).impl_container(cx.tcx) { + if cx.tcx.impl_trait_ref(cid).is_some() { + return; + } + } else { + return; } let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 0d953299189..07bc2ca5d3c 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { match tit_.kind { hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, hir::TraitItemKind::Fn(..) => { - if tit.defaultness.has_value() { + if cx.tcx.impl_defaultness(tit.id.def_id).has_value() { // trait method with default body needs inline in case // an impl is not provided let desc = "a default trait method"; @@ -151,9 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) => return, }; - let trait_def_id = match cx.tcx.associated_item(impl_item.def_id).container { - TraitContainer(cid) => Some(cid), - ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id), + let assoc_item = cx.tcx.associated_item(impl_item.def_id); + let container_id = assoc_item.container_id(cx.tcx); + let trait_def_id = match assoc_item.container { + TraitContainer => Some(container_id), + ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.def_id), }; if let Some(trait_def_id) = trait_def_id { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 04f16fd2161..d2e675a783e 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -345,7 +345,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) -> if line.starts_with("/*") { let src = src[line_start..line_starts.last().unwrap().to_usize() - offset].trim_start(); let mut tokens = tokenize(src); - return src[..tokens.next().unwrap().len] + return src[..tokens.next().unwrap().len as usize] .to_ascii_uppercase() .contains("SAFETY:") && tokens.all(|t| t.kind == TokenKind::Whitespace); diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index eaf260ddfb8..1834e2a2de8 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -141,7 +141,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut left_pos = 0; let left = tokenize(&left) .map(|t| { - let end = left_pos + t.len; + let end = left_pos + t.len as usize; let s = &left[left_pos..end]; left_pos = end; (t, s) @@ -156,7 +156,7 @@ impl HirEqInterExpr<'_, '_, '_> { let mut right_pos = 0; let right = tokenize(&right) .map(|t| { - let end = right_pos + t.len; + let end = right_pos + t.len as usize; let s = &right[right_pos..end]; right_pos = end; (t, s) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 50bb008098d..7493a8685df 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -968,7 +968,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' } }, ExprKind::Closure { .. } => { - let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id(); + let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id); for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) { let local_id = match capture.place.base { PlaceBase::Local(id) => id, diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index 57d548f313d..9187c3551d7 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -41,9 +41,9 @@ fn python() -> &'static str { } else if python2 { PYTHON2 } else { - // We would have returned early if we found that python is installed ... - // maybe this should panic with an error instead? - PYTHON + // Python was not found on path, so exit + eprintln!("Unable to find python in your PATH. Please check it is installed."); + process::exit(1); } } diff --git a/triagebot.toml b/triagebot.toml index f2930b50e3e..ea654192bbf 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -323,6 +323,7 @@ otherwise, make sure you bump the `FORMAT_VERSION` constant. cc = [ "@CraftSpider", "@aDotInTheVoid", + "@Enselic", ] [mentions."src/tools/cargo"] |
