diff options
355 files changed, 6167 insertions, 4173 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f25fdc942b0..e38572f609b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3075,7 +3075,8 @@ mod size_asserts { static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(ExprKind, 72); - static_assert_size!(Fn, 192); + #[cfg(not(bootstrap))] + static_assert_size!(Fn, 184); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 5b72ec2b601..6b0dac7c2f0 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -232,6 +232,8 @@ impl AttrItem { } impl Attribute { + /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example). + /// So `#[doc = "doc"]` will return `false`. pub fn is_doc_comment(&self) -> bool { match self.kind { AttrKind::Normal(..) => false, diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index b0e9fe0469c..90bb01aa216 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7cbfe143b4d..7465706d1a9 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -84,10 +84,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { - let ty = l - .ty - .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + let ty = l.ty.as_ref().map(|t| { + self.lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Variable)) + }); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 77babeb5d39..6fa8d7f0fcd 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -66,7 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); let receiver = self.lower_expr(receiver); let args = @@ -89,14 +89,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -219,7 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::ExprKind::Path(qpath) } @@ -253,7 +253,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -550,12 +550,14 @@ impl<'hir> LoweringContext<'_, 'hir> { async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { - let output = match ret_ty { - Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), - ), - None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), - }; + let output = + match ret_ty { + Some(ty) => hir::FnRetTy::Return(self.lower_ty( + &ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock), + )), + None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), + }; // Resume argument type. We let the compiler infer this to simplify the lowering. It is // fully constrained by `future::from_generator`. @@ -1123,7 +1125,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a tuple struct. let tuple_struct_pat = @@ -1139,7 +1141,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1163,7 +1165,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fields_omitted = match &se.rest { StructRest::Base(e) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 76f63d1d78a..f0717b51d4b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -264,8 +264,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) }); @@ -311,8 +311,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| this.lower_ty(ty, &mut ImplTraitContext::TypeAliasesOpaqueTy), ); hir::ItemKind::TyAlias(ty, generics) } @@ -324,7 +324,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)), ); hir::ItemKind::TyAlias(ty, generics) @@ -333,7 +333,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, variants) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -346,7 +346,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, struct_def) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -355,7 +355,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, vdata) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -383,18 +383,20 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, itctx, |this| { + self.lower_generics(ast_generics, id, &mut itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); - let lowered_ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let lowered_ty = this.lower_ty( + ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ); (trait_ref, lowered_ty) }); @@ -433,11 +435,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -452,11 +454,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, bounds) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -479,7 +481,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (ty, self.lower_const_body(span, body)) } @@ -652,9 +654,9 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { + self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), @@ -665,8 +667,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(ref t, m, _) => { - let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -734,11 +736,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -761,7 +763,8 @@ impl<'hir> LoweringContext<'_, 'hir> { 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 ty = + self.lower_ty(ty, &mut 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), body.is_some()) } @@ -796,15 +799,18 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty( + x, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -857,7 +863,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -884,14 +891,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty(ty, &mut ImplTraitContext::TypeAliasesOpaqueTy); hir::ImplItemKind::TyAlias(ty) } }, @@ -1234,8 +1241,8 @@ impl<'hir> LoweringContext<'_, 'hir> { is_async: Option<NodeId>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1301,7 +1308,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, parent_node_id: NodeId, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1406,7 +1413,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { // Do not create a clause if we do not have anything inside it. @@ -1481,12 +1488,14 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), - bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + bounded_ty: self.lower_ty( + bounded_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) })), span: self.lower_span(span), @@ -1501,16 +1510,20 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }), WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - lhs_ty: self - .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), - rhs_ty: self - .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + lhs_ty: self.lower_ty( + lhs_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), + rhs_ty: self.lower_ty( + rhs_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3a94c7a91b2..e7bbf7dbdec 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -660,6 +660,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// actually used in the HIR, as that would trigger an assertion in the /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// properly. Calling the method twice with the same `NodeId` is fine though. + #[instrument(level = "debug", skip(self), ret)] fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { assert_ne!(ast_node_id, DUMMY_NODE_ID); @@ -693,6 +694,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Generate a new `HirId` without a backing `NodeId`. + #[instrument(level = "debug", skip(self), ret)] fn next_id(&mut self) -> hir::HirId { let owner = self.current_hir_id_owner; let local_id = self.item_local_id_counter; @@ -953,7 +955,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -976,6 +978,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.arena.alloc(hir::GenericArgs::none()) }; + let mut itctx_tait = ImplTraitContext::TypeAliasesOpaqueTy; let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { @@ -1014,7 +1017,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { - (true, ImplTraitContext::TypeAliasesOpaqueTy) + (true, &mut itctx_tait) } // We are in the parameter position, but not within a dyn type: @@ -1096,7 +1099,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), @@ -1158,7 +1161,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: &mut ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1168,7 +1171,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, path: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1210,7 +1213,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: &mut ImplTraitContext) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, @@ -1307,16 +1310,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = t.span; match itctx { ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) + self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx) } ImplTraitContext::TypeAliasesOpaqueTy => { - let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; + let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias, def_node_id, bounds, - nested_itctx, + &mut nested_itctx, ) } ImplTraitContext::Universal => { @@ -1381,14 +1384,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters /// for the lifetimes that get captured (`'x`, in our example above) and reference those. - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] fn lower_opaque_impl_trait( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1561,8 +1564,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - let old_def_id = self.local_def_id(param); - if remapping.get(&old_def_id).is_none() { + if let Some(old_def_id) = self.opt_local_def_id(param) && remapping.get(&old_def_id).is_none() { let node_id = self.next_node_id(); let new_def_id = self.create_def( @@ -1636,11 +1638,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) + self.lower_ty_direct(¶m.ty, &mut ImplTraitContext::Universal) } else { self.lower_ty_direct( ¶m.ty, - ImplTraitContext::Disallowed(match kind { + &mut ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1663,7 +1665,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { match decl.output { FnRetTy::Ty(ref ty) => { - let context = match fn_node_id { + let mut context = match fn_node_id { Some(fn_node_id) if kind.impl_trait_return_allowed() => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { @@ -1681,7 +1683,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -1960,10 +1962,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let context = ImplTraitContext::ReturnPositionOpaqueTy { + let mut context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; - self.lower_ty(ty, context) + self.lower_ty(ty, &mut context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -1989,7 +1991,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( @@ -2101,7 +2103,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(x, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }), synthetic: false, }; @@ -2109,7 +2111,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(&ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2119,7 +2122,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { + fn lower_trait_ref( + &mut self, + p: &TraitRef, + itctx: &mut ImplTraitContext, + ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), @@ -2131,7 +2138,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); @@ -2139,26 +2146,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: &mut ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } + #[instrument(level = "debug", skip(self), ret)] fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } - fn lower_param_bounds_mut<'s>( + fn lower_param_bounds_mut<'s, 'b>( &'s mut self, bounds: &'s [GenericBound], - itctx: ImplTraitContext, - ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> { + itctx: &'b mut ImplTraitContext, + ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> + Captures<'b> + { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } + #[instrument(level = "debug", skip(self), ret)] fn lower_generic_and_bounds( &mut self, node_id: NodeId, @@ -2184,7 +2194,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - ImplTraitContext::Universal, + &mut ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index a1eee1be798..69e6c2c8ad0 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -37,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); break hir::PatKind::Path(qpath); } @@ -63,7 +63,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index de1467b1b07..a3d864023a9 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -22,7 +22,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -156,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ) })), span: self.lower_span(p.span), @@ -180,7 +180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { @@ -316,7 +316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &mut ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -350,12 +350,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct( + ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam), + ) })); let output_ty = match output { - FnRetTy::Ty(ty) => { - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) - } + FnRetTy::Ty(ty) => self + .lower_ty(&ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)), FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index a8ed510866d..bb972a18acb 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -63,7 +63,12 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { sess.emit_err(session_diagnostics::MultipleStabilityLevels { span }); } AttrError::UnsupportedLiteral(reason, is_bytestr) => { - sess.emit_err(session_diagnostics::UnsupportedLiteral { span, reason, is_bytestr }); + sess.emit_err(session_diagnostics::UnsupportedLiteral { + span, + reason, + is_bytestr, + start_point_span: sess.source_map().start_point(span), + }); } } } @@ -1040,18 +1045,16 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> { &name, ), }); - } else { - if matches!( - meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent - ) || int_type_of_word(meta_item.name_or_empty()).is_some() - { - recognised = true; - sess.emit_err(session_diagnostics::InvalidReprHintNoValue { - span: meta_item.span, - name: meta_item.name_or_empty().to_ident_string(), - }); - } + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + sess.emit_err(session_diagnostics::InvalidReprHintNoValue { + span: meta_item.span, + name: meta_item.name_or_empty().to_ident_string(), + }); } } else if let MetaItemKind::List(_) = meta_item.kind { if meta_item.has_name(sym::align) { diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 25cd960dbf1..085175d4bed 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -1,9 +1,11 @@ use std::num::IntErrorKind; use rustc_ast as ast; -use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{ + error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, +}; use rustc_macros::SessionDiagnostic; -use rustc_session::{parse::ParseSess, SessionDiagnostic}; +use rustc_session::SessionDiagnostic; use rustc_span::{Span, Symbol}; use crate::UnsupportedLiteralReason; @@ -49,9 +51,9 @@ pub(crate) struct UnknownMetaItem<'a> { // Manual implementation to be able to format `expected` items correctly. impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>(); - let mut diag = sess.span_diagnostic.struct_span_err_with_code( + let mut diag = handler.struct_span_err_with_code( self.span, fluent::attr::unknown_meta_item, error_code!(E0541), @@ -204,11 +206,12 @@ pub(crate) struct UnsupportedLiteral { pub span: Span, pub reason: UnsupportedLiteralReason, pub is_bytestr: bool, + pub start_point_span: Span, } impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = sess.span_diagnostic.struct_span_err_with_code( + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut diag = handler.struct_span_err_with_code( self.span, match self.reason { UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic, @@ -224,7 +227,7 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { ); if self.is_bytestr { diag.span_suggestion( - sess.source_map().start_point(self.span), + self.start_point_span, fluent::attr::unsupported_literal_suggestion, "", Applicability::MaybeIncorrect, diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 816288eb50b..9f7a4d49989 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -391,7 +391,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { | mir::StatementKind::Retag { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Coverage(..) - | mir::StatementKind::CopyNonOverlapping(..) + | mir::StatementKind::Intrinsic(..) | mir::StatementKind::Nop => {} } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index ec521b1cf0a..3157f861d93 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -1,6 +1,6 @@ use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{BasicBlock, Body, Location, Place, Rvalue}; +use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue}; use rustc_middle::mir::{BorrowKind, Mutability, Operand}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::mir::{Statement, StatementKind}; @@ -63,23 +63,24 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { StatementKind::FakeRead(box (_, _)) => { // Only relevant for initialized/liveness/safety checks. } - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => { + self.consume_operand(location, op); + } + StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping { ref src, ref dst, ref count, - }) => { + })) => { self.consume_operand(location, src); self.consume_operand(location, dst); self.consume_operand(location, count); } - StatementKind::Nop + // Only relevant for mir typeck + StatementKind::AscribeUserType(..) + // Doesn't have any language semantics | StatementKind::Coverage(..) - | StatementKind::AscribeUserType(..) - | StatementKind::Retag { .. } - | StatementKind::StorageLive(..) => { - // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant - // to borrow check. - } + // Does not actually affect borrowck + | StatementKind::StorageLive(..) => {} StatementKind::StorageDead(local) => { self.access_place( location, @@ -88,7 +89,10 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { LocalMutationIsAllowed::Yes, ); } - StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { + StatementKind::Nop + | StatementKind::Retag { .. } + | StatementKind::Deinit(..) + | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 20c22575bd1..ec652f85217 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -26,8 +26,8 @@ use rustc_index::bit_set::ChunkedBitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::{ - traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem, - PlaceRef, VarDebugInfoContents, + traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, + Place, PlaceElem, PlaceRef, VarDebugInfoContents, }; use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; @@ -591,22 +591,19 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx flow_state, ); } - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - .. - }) => { - span_bug!( + StatementKind::Intrinsic(box ref kind) => match kind { + NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state), + NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( span, "Unexpected CopyNonOverlapping, should only appear after lower_intrinsics", ) } - StatementKind::Nop + // Only relevant for mir typeck + StatementKind::AscribeUserType(..) + // Doesn't have any language semantics | StatementKind::Coverage(..) - | StatementKind::AscribeUserType(..) - | StatementKind::Retag { .. } - | StatementKind::StorageLive(..) => { - // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant - // to borrow check. - } + // Does not actually affect borrowck + | StatementKind::StorageLive(..) => {} StatementKind::StorageDead(local) => { self.access_place( location, @@ -616,7 +613,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx flow_state, ); } - StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { + StatementKind::Nop + | StatementKind::Retag { .. } + | StatementKind::Deinit(..) + | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a620c987052..fc0e95f30c9 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1302,12 +1302,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } } - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - .. - }) => span_bug!( - stmt.source_info.span, - "Unexpected StatementKind::CopyNonOverlapping, should only appear after lowering_intrinsics", - ), + StatementKind::Intrinsic(box ref kind) => match kind { + NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location), + NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( + stmt.source_info.span, + "Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics", + ), + }, StatementKind::FakeRead(..) | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index c412e451a03..2aa11ac2eea 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -794,20 +794,31 @@ fn codegen_stmt<'tcx>( | StatementKind::AscribeUserType(..) => {} StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"), - StatementKind::CopyNonOverlapping(inner) => { - let dst = codegen_operand(fx, &inner.dst); - let pointee = dst - .layout() - .pointee_info_at(fx, rustc_target::abi::Size::ZERO) - .expect("Expected pointer"); - let dst = dst.load_scalar(fx); - let src = codegen_operand(fx, &inner.src).load_scalar(fx); - let count = codegen_operand(fx, &inner.count).load_scalar(fx); - let elem_size: u64 = pointee.size.bytes(); - let bytes = - if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; - fx.bcx.call_memcpy(fx.target_config, dst, src, bytes); - } + StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic { + // We ignore `assume` intrinsics, they are only useful for optimizations + NonDivergingIntrinsic::Assume(_) => {} + NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping { + src, + dst, + count, + }) => { + let dst = codegen_operand(fx, dst); + let pointee = dst + .layout() + .pointee_info_at(fx, rustc_target::abi::Size::ZERO) + .expect("Expected pointer"); + let dst = dst.load_scalar(fx); + let src = codegen_operand(fx, src).load_scalar(fx); + let count = codegen_operand(fx, count).load_scalar(fx); + let elem_size: u64 = pointee.size.bytes(); + let bytes = if elem_size != 1 { + fx.bcx.ins().imul_imm(count, elem_size as i64) + } else { + count + }; + fx.bcx.call_memcpy(fx.target_config, dst, src, bytes); + } + }, } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 9224f499339..0305341da78 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -536,9 +536,11 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( { return None; } - StatementKind::CopyNonOverlapping(_) => { - return None; - } // conservative handling + StatementKind::Intrinsic(ref intrinsic) => match **intrinsic { + NonDivergingIntrinsic::CopyNonOverlapping(..) => return None, + NonDivergingIntrinsic::Assume(..) => {} + }, + // conservative handling StatementKind::Assign(_) | StatementKind::FakeRead(_) | StatementKind::SetDiscriminant { .. } diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index e41ae1fbdba..97b395bcd05 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -42,10 +42,10 @@ pub(crate) fn codegen_set_discriminant<'tcx>( Variants::Multiple { tag: _, tag_field, - tag_encoding: TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + tag_encoding: TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, variants: _, } => { - if variant_index != dataful_variant { + if variant_index != untagged_variant { let niche = place.place_field(fx, mir::Field::new(tag_field)); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = ty::ScalarInt::try_from_uint( @@ -113,7 +113,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let res = CValue::by_val(val, dest_layout); dest.write_cvalue(fx, res); } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check // whether the result is in range for the niche variants. @@ -169,8 +169,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>( fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32())) }; - let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32())); - let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant); + let untagged_variant = + fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32())); + let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant); let res = CValue::by_val(discr, dest_layout); dest.write_cvalue(fx, res); } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 39e9e784a47..0cd9332a58b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -357,9 +357,6 @@ fn codegen_regular_intrinsic_call<'tcx>( let usize_layout = fx.layout_of(fx.tcx.types.usize); match intrinsic { - sym::assume => { - intrinsic_args!(fx, args => (_a); intrinsic); - } sym::likely | sym::unlikely => { intrinsic_args!(fx, args => (a); intrinsic); diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index ccb6cbbc2c8..aa1c271c31c 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -158,10 +158,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { None } - fn zst_to_backend(&self, _ty: Type<'gcc>) -> RValue<'gcc> { - self.const_undef(self.type_ix(0)) - } - fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 13e437cfbf7..488ea72c3b7 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -226,10 +226,6 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { }) } - fn zst_to_backend(&self, _llty: &'ll Type) -> &'ll Value { - self.const_undef(self.type_ix(0)) - } - fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index daec9303b2c..129e336c7e4 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -99,7 +99,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0; /// compiler versions. /// /// Niche-tag enums have one special variant, usually called the -/// "dataful variant". This variant has a field that +/// "untagged variant". This variant has a field that /// doubles as the tag of the enum. The variant is active when the value of /// that field is within a pre-defined range. Therefore the variant struct /// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in @@ -249,7 +249,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( None, ), Variants::Multiple { - tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag_encoding: TagEncoding::Niche { untagged_variant, .. }, ref variants, tag_field, .. @@ -260,7 +260,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_di_node, variants.indices(), tag_field, - Some(dataful_variant), + Some(untagged_variant), ), } }, @@ -391,7 +391,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( enum_type_di_node: &'ll DIType, variant_indices: impl Iterator<Item = VariantIdx> + Clone, tag_field: usize, - dataful_variant_index: Option<VariantIdx>, + untagged_variant_index: Option<VariantIdx>, ) -> SmallVec<&'ll DIType> { let tag_base_type = super::tag_base_type(cx, enum_type_and_layout); @@ -436,7 +436,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( variant_names_type_di_node, tag_base_type, tag_field, - dataful_variant_index, + untagged_variant_index, ) } @@ -472,7 +472,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( enum_or_generator_type_and_layout: TyAndLayout<'tcx>, enum_or_generator_type_di_node: &'ll DIType, variant_index: VariantIdx, - dataful_variant_index: Option<VariantIdx>, + untagged_variant_index: Option<VariantIdx>, variant_struct_type_di_node: &'ll DIType, variant_names_type_di_node: &'ll DIType, tag_base_type_di_node: &'ll DIType, @@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( } } DiscrResult::Range(min, max) => { - assert_eq!(Some(variant_index), dataful_variant_index); + assert_eq!(Some(variant_index), untagged_variant_index); if is_128_bits { DiscrKind::Range128(min, max) } else { @@ -757,7 +757,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( discr_type_di_node: &'ll DIType, tag_base_type: Ty<'tcx>, tag_field: usize, - dataful_variant_index: Option<VariantIdx>, + untagged_variant_index: Option<VariantIdx>, ) -> SmallVec<&'ll DIType> { let tag_base_type_di_node = type_di_node(cx, tag_base_type); let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1); @@ -776,7 +776,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( enum_type_and_layout, enum_type_di_node, variant_member_info.variant_index, - dataful_variant_index, + untagged_variant_index, variant_member_info.variant_struct_type_di_node, discr_type_di_node, tag_base_type_di_node, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 9b3d080bfd6..14044d0f99b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -417,7 +417,7 @@ impl DiscrResult { /// Returns the discriminant value corresponding to the variant index. /// /// Will return `None` if there is less than two variants (because then the enum won't have) -/// a tag, and if this is the dataful variant of a niche-layout enum (because then there is no +/// a tag, and if this is the untagged variant of a niche-layout enum (because then there is no /// single discriminant value). fn compute_discriminant_value<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, @@ -430,11 +430,11 @@ fn compute_discriminant_value<'ll, 'tcx>( enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val, ), &Variants::Multiple { - tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, + tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, untagged_variant }, tag, .. } => { - if variant_index == dataful_variant { + if variant_index == untagged_variant { let valid_range = enum_type_and_layout .for_variant(cx, variant_index) .largest_niche diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index dae90a43f26..becbccc434d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -378,7 +378,7 @@ fn build_discr_member_di_node<'ll, 'tcx>( /// /// The DW_AT_discr_value is optional, and is omitted if /// - This is the only variant of a univariant enum (i.e. their is no discriminant) -/// - This is the "dataful" variant of a niche-layout enum +/// - This is the "untagged" variant of a niche-layout enum /// (where only the other variants are identified by a single value) /// /// There is only ever a single member, the type of which is a struct that describes the diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e9171823c24..a3fed88cc4b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,6 +1,6 @@ use rustc_arena::TypedArena; use rustc_ast::CRATE_NODE_ID; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorGuaranteed, Handler}; @@ -1714,6 +1714,13 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor /// that are necessary for the linking. They are only present in symbol table but not actually /// used in any sections, so the linker will therefore pick relevant rlibs for linking, but /// unused `#[no_mangle]` or `#[used]` can still be discard by GC sections. +/// +/// There's a few internal crates in the standard library (aka libcore and +/// libstd) which actually have a circular dependence upon one another. This +/// currently arises through "weak lang items" where libcore requires things +/// like `rust_begin_unwind` but libstd ends up defining it. To get this +/// circular dependence to work correctly we declare some of these things +/// in this synthetic object. fn add_linked_symbol_object( cmd: &mut dyn Linker, sess: &Session, @@ -2333,65 +2340,10 @@ fn add_upstream_rust_crates<'a>( // crates. let deps = &codegen_results.crate_info.used_crates; - // There's a few internal crates in the standard library (aka libcore and - // libstd) which actually have a circular dependence upon one another. This - // currently arises through "weak lang items" where libcore requires things - // like `rust_begin_unwind` but libstd ends up defining it. To get this - // circular dependence to work correctly in all situations we'll need to be - // sure to correctly apply the `--start-group` and `--end-group` options to - // GNU linkers, otherwise if we don't use any other symbol from the standard - // library it'll get discarded and the whole application won't link. - // - // In this loop we're calculating the `group_end`, after which crate to - // pass `--end-group` and `group_start`, before which crate to pass - // `--start-group`. We currently do this by passing `--end-group` after - // the first crate (when iterating backwards) that requires a lang item - // defined somewhere else. Once that's set then when we've defined all the - // necessary lang items we'll pass `--start-group`. - // - // Note that this isn't amazing logic for now but it should do the trick - // for the current implementation of the standard library. - let mut group_end = None; - let mut group_start = None; - // Crates available for linking thus far. - let mut available = FxHashSet::default(); - // Crates required to satisfy dependencies discovered so far. - let mut required = FxHashSet::default(); - - let info = &codegen_results.crate_info; - for &cnum in deps.iter().rev() { - if let Some(missing) = info.missing_lang_items.get(&cnum) { - let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied()); - required.extend(missing_crates); - } - - required.insert(Some(cnum)); - available.insert(Some(cnum)); - - if required.len() > available.len() && group_end.is_none() { - group_end = Some(cnum); - } - if required.len() == available.len() && group_end.is_some() { - group_start = Some(cnum); - break; - } - } - - // If we didn't end up filling in all lang items from upstream crates then - // we'll be filling it in with our crate. This probably means we're the - // standard library itself, so skip this for now. - if group_end.is_some() && group_start.is_none() { - group_end = None; - } - let mut compiler_builtins = None; let search_path = OnceCell::new(); for &cnum in deps.iter() { - if group_start == Some(cnum) { - cmd.group_start(); - } - // We may not pass all crates through to the linker. Some crates may // appear statically in an existing dylib, meaning we'll pick up all the // symbols from the dylib. @@ -2451,6 +2403,14 @@ fn add_upstream_rust_crates<'a>( bundle: Some(false), whole_archive: Some(false) | None, } => { + // HACK/FIXME: Fixup a circular dependency between libgcc and libc + // with glibc. This logic should be moved to the libc crate. + if sess.target.os == "linux" + && sess.target.env == "gnu" + && name == "c" + { + cmd.link_staticlib("gcc", false); + } cmd.link_staticlib(name, lib.verbatim.unwrap_or(false)); } NativeLibKind::LinkArg => { @@ -2470,10 +2430,6 @@ fn add_upstream_rust_crates<'a>( } Linkage::Dynamic => add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0), } - - if group_end == Some(cnum) { - cmd.group_end(); - } } // compiler-builtins are always placed last to ensure that they're diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8c6f526b054..949a356fce1 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -183,8 +183,6 @@ pub trait Linker { fn no_default_libraries(&mut self); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]); fn subsystem(&mut self, subsystem: &str); - fn group_start(&mut self); - fn group_end(&mut self); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} fn add_no_exec(&mut self) {} @@ -730,18 +728,6 @@ impl<'a> Linker for GccLinker<'a> { self.hint_dynamic(); // Reset to default before returning the composed command line. } - fn group_start(&mut self) { - if self.takes_hints() { - self.linker_arg("--start-group"); - } - } - - fn group_end(&mut self) { - if self.takes_hints() { - self.linker_arg("--end-group"); - } - } - fn linker_plugin_lto(&mut self) { match self.sess.opts.cg.linker_plugin_lto { LinkerPluginLto::Disabled => { @@ -1019,10 +1005,6 @@ impl<'a> Linker for MsvcLinker<'a> { } } - // MSVC doesn't need group indicators - fn group_start(&mut self) {} - fn group_end(&mut self) {} - fn linker_plugin_lto(&mut self) { // Do nothing } @@ -1165,10 +1147,6 @@ impl<'a> Linker for EmLinker<'a> { // noop } - // Appears not necessary on Emscripten - fn group_start(&mut self) {} - fn group_end(&mut self) {} - fn linker_plugin_lto(&mut self) { // Do nothing } @@ -1344,10 +1322,6 @@ impl<'a> Linker for WasmLd<'a> { fn subsystem(&mut self, _subsystem: &str) {} - // Not needed for now with LLD - fn group_start(&mut self) {} - fn group_end(&mut self) {} - fn linker_plugin_lto(&mut self) { // Do nothing for now } @@ -1476,14 +1450,6 @@ impl<'a> Linker for L4Bender<'a> { self.hint_static(); // Reset to default before returning the composed command line. } - fn group_start(&mut self) { - self.cmd.arg("--start-group"); - } - - fn group_end(&mut self) { - self.cmd.arg("--end-group"); - } - fn linker_plugin_lto(&mut self) {} fn control_flow_guard(&mut self) {} @@ -1664,10 +1630,6 @@ impl<'a> Linker for PtxLinker<'a> { fn subsystem(&mut self, _subsystem: &str) {} - fn group_start(&mut self) {} - - fn group_end(&mut self) {} - fn linker_plugin_lto(&mut self) {} } @@ -1777,9 +1739,5 @@ impl<'a> Linker for BpfLinker<'a> { fn subsystem(&mut self, _subsystem: &str) {} - fn group_start(&mut self) {} - - fn group_end(&mut self) {} - fn linker_plugin_lto(&mut self) {} } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 6e482062383..5f140d709d8 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -12,7 +12,7 @@ use crate::traits::*; use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; use rustc_attr as attr; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::par_iter; @@ -21,10 +21,12 @@ use rustc_data_structures::sync::ParallelIterator; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; +use rustc_hir::weak_lang_items::WEAK_ITEMS_SYMBOLS; use rustc_index::vec::Idx; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols; +use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; @@ -34,6 +36,7 @@ use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_session::Session; use rustc_span::symbol::sym; +use rustc_span::Symbol; use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_target::abi::{Align, VariantIdx}; @@ -815,21 +818,16 @@ impl CrateInfo { crate_name: Default::default(), used_crates, used_crate_source: Default::default(), - lang_item_to_crate: Default::default(), - missing_lang_items: Default::default(), dependency_formats: tcx.dependency_formats(()).clone(), windows_subsystem, natvis_debugger_visualizers: Default::default(), }; - let lang_items = tcx.lang_items(); - let crates = tcx.crates(()); let n_crates = crates.len(); info.native_libraries.reserve(n_crates); info.crate_name.reserve(n_crates); info.used_crate_source.reserve(n_crates); - info.missing_lang_items.reserve(n_crates); for &cnum in crates.iter() { info.native_libraries @@ -847,17 +845,37 @@ impl CrateInfo { if tcx.is_no_builtins(cnum) { info.is_no_builtins.insert(cnum); } - let missing = tcx.missing_lang_items(cnum); - for &item in missing.iter() { - if let Ok(id) = lang_items.require(item) { - info.lang_item_to_crate.insert(item, id.krate); - } - } + } - // No need to look for lang items that don't actually need to exist. - let missing = - missing.iter().cloned().filter(|&l| lang_items::required(tcx, l)).collect(); - info.missing_lang_items.insert(cnum, missing); + // Handle circular dependencies in the standard library. + // See comment before `add_linked_symbol_object` function for the details. + // With msvc-like linkers it's both unnecessary (they support circular dependencies), + // and causes linking issues (when weak lang item symbols are "privatized" by LTO). + let target = &tcx.sess.target; + if !target.is_like_msvc { + let missing_weak_lang_items: FxHashSet<&Symbol> = info + .used_crates + .iter() + .flat_map(|cnum| { + tcx.missing_lang_items(*cnum) + .iter() + .filter(|l| lang_items::required(tcx, **l)) + .filter_map(|item| WEAK_ITEMS_SYMBOLS.get(item)) + }) + .collect(); + let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" }; + info.linked_symbols + .iter_mut() + .filter(|(crate_type, _)| { + !matches!(crate_type, CrateType::Rlib | CrateType::Staticlib) + }) + .for_each(|(_, linked_symbols)| { + linked_symbols.extend( + missing_weak_lang_items + .iter() + .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)), + ) + }); } let embed_visualizers = tcx.sess.crate_types().iter().any(|&crate_type| match crate_type { @@ -878,7 +896,7 @@ impl CrateInfo { } }); - if tcx.sess.target.is_like_msvc && embed_visualizers { + if target.is_like_msvc && embed_visualizers { info.natvis_debugger_visualizers = collect_debugger_visualizers_transitive(tcx, DebuggerVisualizerType::Natvis); } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 0faf51b062b..52da7abcac5 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,7 +25,6 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; -use rustc_hir::LangItem; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -152,8 +151,6 @@ pub struct CrateInfo { pub used_libraries: Vec<NativeLib>, pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>, pub used_crates: Vec<CrateNum>, - pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>, - pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>, pub dependency_formats: Lrc<Dependencies>, pub windows_subsystem: Option<String>, pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 16aad07194d..6393dd9d634 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -77,10 +77,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let llval = match name { - sym::assume => { - bx.assume(args[0].immediate()); - return; - } sym::abort => { bx.abort(); return; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index c612634fce2..37b1e036247 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -72,10 +72,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ) -> Self { let layout = bx.layout_of(ty); - if layout.is_zst() { - return OperandRef::new_zst(bx, layout); - } - let val = match val { ConstValue::Scalar(x) => { let Abi::Scalar(scalar) = layout.abi else { @@ -84,10 +80,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); OperandValue::Immediate(llval) } - ConstValue::ZeroSized => { - let llval = bx.zst_to_backend(bx.immediate_backend_type(layout)); - OperandValue::Immediate(llval) - } + ConstValue::ZeroSized => return OperandRef::new_zst(bx, layout), ConstValue::Slice { data, start, end } => { let Abi::ScalarPair(a_scalar, _) = layout.abi else { bug!("from_const: invalid ScalarPair layout: {:#?}", layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 04b8c8636f6..13d8f6eddd1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { }; bx.intcast(tag.immediate(), cast_to, signed) } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check // whether the result is in range for the niche variants. let niche_llty = bx.cx().immediate_backend_type(tag.layout); @@ -302,7 +302,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx.select( is_niche, niche_discr, - bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64), + bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64), ) } } @@ -337,11 +337,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } Variants::Multiple { tag_encoding: - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, tag_field, .. } => { - if variant_index != dataful_variant { + if variant_index != untagged_variant { let niche = self.project_field(bx, tag_field); let niche_llty = bx.cx().immediate_backend_type(niche.layout); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index f452f29883f..1db0fb3a6f1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,4 +1,5 @@ use rustc_middle::mir; +use rustc_middle::mir::NonDivergingIntrinsic; use super::FunctionCx; use super::LocalRef; @@ -73,11 +74,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope); bx } - mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping { - ref src, - ref dst, - ref count, - }) => { + mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { + let op_val = self.codegen_operand(&mut bx, op); + bx.assume(op_val.immediate()); + bx + } + mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + mir::CopyNonOverlapping { ref count, ref src, ref dst }, + )) => { let dst_val = self.codegen_operand(&mut bx, dst); let src_val = self.codegen_operand(&mut bx, src); let count = self.codegen_operand(&mut bx, count).immediate(); diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 8a91d4735ba..fdc7a30e841 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -29,7 +29,6 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value; fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value; - fn zst_to_backend(&self, llty: Self::Type) -> Self::Value; fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index adda9639990..2f415a8c9c7 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::{ self, interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar}, - BinOp, + BinOp, NonDivergingIntrinsic, }; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; @@ -506,12 +506,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // These just return their argument self.copy_op(&args[0], dest, /*allow_transmute*/ false)?; } - sym::assume => { - let cond = self.read_scalar(&args[0])?.to_bool()?; - if !cond { - throw_ub_format!("`assume` intrinsic called with `false`"); - } - } sym::raw_eq => { let result = self.raw_eq_intrinsic(&args[0], &args[1])?; self.write_scalar(result, dest)?; @@ -536,6 +530,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(true) } + pub(super) fn emulate_nondiverging_intrinsic( + &mut self, + intrinsic: &NonDivergingIntrinsic<'tcx>, + ) -> InterpResult<'tcx> { + match intrinsic { + NonDivergingIntrinsic::Assume(op) => { + let op = self.eval_operand(op, None)?; + let cond = self.read_scalar(&op)?.to_bool()?; + if !cond { + throw_ub_format!("`assume` called with `false`"); + } + Ok(()) + } + NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping { + count, + src, + dst, + }) => { + let src = self.eval_operand(src, None)?; + let dst = self.eval_operand(dst, None)?; + let count = self.eval_operand(count, None)?; + self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true) + } + } + } + pub fn exact_div( &mut self, a: &ImmTy<'tcx, M::Provenance>, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 35c2cf8102d..ba041810bd1 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -718,7 +718,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Return the cast value, and the index. (discr_val, index.0) } - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { let tag_val = tag_val.to_scalar(); // Compute the variant this niche value/"tag" corresponds to. With niche layout, // discriminant (encoded in niche/tag) and variant index are the same. @@ -736,7 +736,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) } - dataful_variant + untagged_variant } Ok(tag_bits) => { let tag_bits = tag_bits.assert_bits(tag_layout.size); @@ -766,7 +766,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(usize::try_from(variant_index).unwrap() < variants_len); VariantIdx::from_u32(variant_index) } else { - dataful_variant + untagged_variant } } }; @@ -780,13 +780,13 @@ 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"))] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(Immediate, 56); - static_assert_size!(ImmTy<'_>, 72); - static_assert_size!(Operand, 64); - static_assert_size!(OpTy<'_>, 88); + static_assert_size!(Immediate, 48); + static_assert_size!(ImmTy<'_>, 64); + static_assert_size!(Operand, 56); + static_assert_size!(OpTy<'_>, 80); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index a03b0dfb603..b328892906d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -817,7 +817,7 @@ where } abi::Variants::Multiple { tag_encoding: - TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, tag: tag_layout, tag_field, .. @@ -825,7 +825,7 @@ where // No need to validate that the discriminant here because the // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. - if variant_index != dataful_variant { + if variant_index != untagged_variant { let variants_start = niche_variants.start().as_u32(); let variant_index_relative = variant_index .as_u32() @@ -890,6 +890,8 @@ mod size_asserts { static_assert_size!(MemPlaceMeta, 24); static_assert_size!(MemPlace, 40); static_assert_size!(MPlaceTy<'_>, 64); - static_assert_size!(Place, 48); - static_assert_size!(PlaceTy<'_>, 72); + #[cfg(not(bootstrap))] + static_assert_size!(Place, 40); + #[cfg(not(bootstrap))] + static_assert_size!(PlaceTy<'_>, 64); } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 6b827149f50..c6e04cbfb6b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -114,13 +114,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::retag(self, *kind, &dest)?; } - // Call CopyNonOverlapping - CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => { - let src = self.eval_operand(src, None)?; - let dst = self.eval_operand(dst, None)?; - let count = self.eval_operand(count, None)?; - self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?; - } + Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, // Statements we do not track. AscribeUserType(..) => {} 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 cbfdb47dd1a..3fa40dc3059 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -678,7 +678,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => {} } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b7988625839..783ab350faa 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -7,9 +7,10 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, Local, Location, - MirPass, MirPhase, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RuntimePhase, Rvalue, - SourceScope, Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK, + traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, + Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, + ProjectionElem, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, + TerminatorKind, UnOp, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::Subst; @@ -636,11 +637,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - ref src, - ref dst, - ref count, - }) => { + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => { + let ty = op.ty(&self.body.local_decls, self.tcx); + if !ty.is_bool() { + self.fail( + location, + format!("`assume` argument must be `bool`, but got: `{}`", ty), + ); + } + } + StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + CopyNonOverlapping { src, dst, count }, + )) => { let src_ty = src.ty(&self.body.local_decls, self.tcx); let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) { src_deref.ty diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 07a96dd7dbb..e351b650a16 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -117,6 +117,10 @@ pub trait ObligationProcessor { } /// The result type used by `process_obligation`. +// `repr(C)` to inhibit the niche filling optimization. Otherwise, the `match` appearing +// in `process_obligations` is significantly slower, which can substantially affect +// benchmarks like `rustc-perf`'s inflate and keccak. +#[repr(C)] #[derive(Debug)] pub enum ProcessResult<O, E> { Unchanged, diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 60086cd6e47..2899b8304bc 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -104,9 +104,67 @@ infer_relate_object_bound = ...so that it can be closed over into an object infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> -[true] ... -*[false] {""} + [true] ... + *[false] {""} } infer_relate_param_bound_2 = ...that is required by this bound infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait + +infer_nothing = {""} + +infer_lifetime_mismatch = lifetime mismatch + +infer_declared_different = this parameter and the return type are declared with different lifetimes... +infer_data_returned = ...but data{$label_var1_exists -> + [true] {" "}from `{$label_var1}` + *[false] {""} +} is returned here + +infer_data_lifetime_flow = ...but data with one lifetime flows into the other here +infer_declared_multiple = this type is declared with multiple lifetimes... +infer_types_declared_different = these two types are declared with different lifetimes... +infer_data_flows = ...but data{$label_var1_exists -> + [true] -> {" "}from `{$label_var1}` + *[false] -> {""} +} flows{$label_var2_exists -> + [true] -> {" "}into `{$label_var2}` + *[false] -> {""} +} here + +infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl -> + [true] {" "}and update trait if needed + *[false] {""} +} +infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime + +infer_region_explanation = {$pref_kind -> + *[should_not_happen] [{$pref_kind}] + [empty] {""} +}{$pref_kind -> + [empty] {""} + *[other] {" "} +}{$desc_kind -> + *[should_not_happen] [{$desc_kind}] + [restatic] the static lifetime + [reempty] the empty lifetime + [reemptyuni] the empty lifetime in universe {$desc_arg} + [revar] lifetime {$desc_arg} + + [as_defined] the lifetime `{$desc_arg}` as defined here + [as_defined_anon] the anonymous lifetime as defined here + [defined_here] the anonymous lifetime defined here + [anon_num_here] the anonymous lifetime #{$desc_num_arg} defined here + [defined_here_reg] the lifetime `{$desc_arg}` as defined here +}{$suff_kind -> + *[should_not_happen] [{$suff_kind}] + [empty]{""} + [continues] ... +} + +infer_mismatched_static_lifetime = incompatible lifetime on type +infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +infer_msl_introduces_static = introduces a `'static` lifetime requirement +infer_msl_unmet_req = because this has an unmet lifetime requirement +infer_msl_trait_note = this has an implicit `'static` lifetime requirement +infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68abdd0bad1..513225e1606 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,8 +69,8 @@ pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a, ErrorGuaranteed>>; // (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.) #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24); +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] +rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] pub enum SuggestionStyle { @@ -1250,14 +1250,14 @@ impl HandlerInner { fn treat_err_as_bug(&self) -> bool { self.flags.treat_err_as_bug.map_or(false, |c| { - self.err_count() - + self.lint_err_count - + self.delayed_span_bugs.len() - + self.delayed_good_path_bugs.len() - >= c.get() + self.err_count() + self.lint_err_count + self.delayed_bug_count() >= c.get() }) } + fn delayed_bug_count(&self) -> usize { + self.delayed_span_bugs.len() + self.delayed_good_path_bugs.len() + } + fn print_error_count(&mut self, registry: &Registry) { self.emit_stashed_diagnostics(); @@ -1412,12 +1412,7 @@ impl HandlerInner { // incrementing `err_count` by one, so we need to +1 the comparing. // FIXME: Would be nice to increment err_count in a more coherent way. if self.flags.treat_err_as_bug.map_or(false, |c| { - self.err_count() - + self.lint_err_count - + self.delayed_span_bugs.len() - + self.delayed_good_path_bugs.len() - + 1 - >= c.get() + self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() }) { // FIXME: don't abort here if report_delayed_bugs is off self.span_bug(sp, msg); @@ -1518,14 +1513,24 @@ impl HandlerInner { if self.treat_err_as_bug() { match ( self.err_count() + self.lint_err_count, + self.delayed_bug_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0), ) { - (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), - (0 | 1, _) => {} - (count, as_bug) => panic!( - "aborting after {} errors due to `-Z treat-err-as-bug={}`", - count, as_bug, - ), + (1, 0, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), + (0, 1, 1) => panic!("aborting due delayed bug with `-Z treat-err-as-bug=1`"), + (count, delayed_count, as_bug) => { + if delayed_count > 0 { + panic!( + "aborting after {} errors and {} delayed bugs due to `-Z treat-err-as-bug={}`", + count, delayed_count, as_bug, + ) + } else { + panic!( + "aborting after {} errors due to `-Z treat-err-as-bug={}`", + count, as_bug, + ) + } + } } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 50e7c5d2d04..a668c0e95ce 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3473,12 +3473,15 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 40); + #[cfg(not(bootstrap))] + static_assert_size!(GenericArg<'_>, 32); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); - static_assert_size!(ImplItem<'_>, 88); - static_assert_size!(ImplItemKind<'_>, 40); + #[cfg(not(bootstrap))] + static_assert_size!(ImplItem<'_>, 80); + #[cfg(not(bootstrap))] + static_assert_size!(ImplItemKind<'_>, 32); static_assert_size!(Item<'_>, 80); static_assert_size!(ItemKind<'_>, 48); static_assert_size!(Local<'_>, 64); @@ -3490,8 +3493,10 @@ mod size_asserts { static_assert_size!(QPath<'_>, 24); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - static_assert_size!(TraitItem<'_>, 96); - static_assert_size!(TraitItemKind<'_>, 56); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItem<'static>, 88); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(Ty<'_>, 72); static_assert_size!(TyKind<'_>, 56); } diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index b6a85c0472e..da9c9c1216e 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -18,6 +18,12 @@ pub static WEAK_ITEMS_REFS: LazyLock<FxIndexMap<Symbol, LangItem>> = LazyLock::n map }); +pub static WEAK_ITEMS_SYMBOLS: LazyLock<FxIndexMap<LangItem, Symbol>> = LazyLock::new(|| { + let mut map = FxIndexMap::default(); + $(map.insert(LangItem::$item, sym::$sym);)* + map +}); + pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> { lang_items::extract(attrs).and_then(|(name, _)| { diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs deleted file mode 100644 index 938f8aa77a5..00000000000 --- a/compiler/rustc_infer/src/errors.rs +++ /dev/null @@ -1,254 +0,0 @@ -use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString}; -use rustc_hir::FnRetTy; -use rustc_macros::SessionDiagnostic; -use rustc_span::{BytePos, Span}; - -use crate::infer::error_reporting::{ - need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, - ObligationCauseAsDiagArg, -}; - -#[derive(SessionDiagnostic)] -#[diag(infer::opaque_hidden_type)] -pub struct OpaqueHiddenTypeDiag { - #[primary_span] - #[label] - pub span: Span, - #[note(infer::opaque_type)] - pub opaque_type: Span, - #[note(infer::hidden_type)] - pub hidden_type: Span, -} - -#[derive(SessionDiagnostic)] -#[diag(infer::type_annotations_needed, code = "E0282")] -pub struct AnnotationRequired<'a> { - #[primary_span] - pub span: Span, - pub source_kind: &'static str, - pub source_name: &'a str, - #[label] - pub failure_span: Option<Span>, - #[subdiagnostic] - pub bad_label: Option<InferenceBadError<'a>>, - #[subdiagnostic] - pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, - #[subdiagnostic] - pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, -} - -// Copy of `AnnotationRequired` for E0283 -#[derive(SessionDiagnostic)] -#[diag(infer::type_annotations_needed, code = "E0283")] -pub struct AmbigousImpl<'a> { - #[primary_span] - pub span: Span, - pub source_kind: &'static str, - pub source_name: &'a str, - #[label] - pub failure_span: Option<Span>, - #[subdiagnostic] - pub bad_label: Option<InferenceBadError<'a>>, - #[subdiagnostic] - pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, - #[subdiagnostic] - pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, -} - -// Copy of `AnnotationRequired` for E0284 -#[derive(SessionDiagnostic)] -#[diag(infer::type_annotations_needed, code = "E0284")] -pub struct AmbigousReturn<'a> { - #[primary_span] - pub span: Span, - pub source_kind: &'static str, - pub source_name: &'a str, - #[label] - pub failure_span: Option<Span>, - #[subdiagnostic] - pub bad_label: Option<InferenceBadError<'a>>, - #[subdiagnostic] - pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, - #[subdiagnostic] - pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, -} - -#[derive(SessionDiagnostic)] -#[diag(infer::need_type_info_in_generator, code = "E0698")] -pub struct NeedTypeInfoInGenerator<'a> { - #[primary_span] - pub span: Span, - pub generator_kind: GeneratorKindAsDiagArg, - #[subdiagnostic] - pub bad_label: InferenceBadError<'a>, -} - -// Used when a better one isn't available -#[derive(SessionSubdiagnostic)] -#[label(infer::label_bad)] -pub struct InferenceBadError<'a> { - #[primary_span] - pub span: Span, - pub bad_kind: &'static str, - pub prefix_kind: UnderspecifiedArgKind, - pub has_parent: bool, - pub prefix: &'a str, - pub parent_prefix: &'a str, - pub parent_name: String, - pub name: String, -} - -#[derive(SessionSubdiagnostic)] -pub enum SourceKindSubdiag<'a> { - #[suggestion_verbose( - infer::source_kind_subdiag_let, - code = ": {type_name}", - applicability = "has-placeholders" - )] - LetLike { - #[primary_span] - span: Span, - name: String, - type_name: String, - kind: &'static str, - x_kind: &'static str, - prefix_kind: UnderspecifiedArgKind, - prefix: &'a str, - arg_name: String, - }, - #[label(infer::source_kind_subdiag_generic_label)] - GenericLabel { - #[primary_span] - span: Span, - is_type: bool, - param_name: String, - parent_exists: bool, - parent_prefix: String, - parent_name: String, - }, - #[suggestion_verbose( - infer::source_kind_subdiag_generic_suggestion, - code = "::<{args}>", - applicability = "has-placeholders" - )] - GenericSuggestion { - #[primary_span] - span: Span, - arg_count: usize, - args: String, - }, -} - -// Has to be implemented manually because multipart suggestions are not supported by the derive macro. -// Would be a part of `SourceKindSubdiag` otherwise. -pub enum SourceKindMultiSuggestion<'a> { - FullyQualified { - span: Span, - def_path: String, - adjustment: &'a str, - successor: (&'a str, BytePos), - }, - ClosureReturn { - ty_info: String, - data: &'a FnRetTy<'a>, - should_wrap_expr: Option<Span>, - }, -} - -impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { - match self { - Self::FullyQualified { span, def_path, adjustment, successor } => { - let suggestion = vec![ - (span.shrink_to_lo(), format!("{def_path}({adjustment}")), - (span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()), - ]; - diag.multipart_suggestion_verbose( - fluent::infer::source_kind_fully_qualified, - suggestion, - rustc_errors::Applicability::HasPlaceholders, - ); - } - Self::ClosureReturn { ty_info, data, should_wrap_expr } => { - let (arrow, post) = match data { - FnRetTy::DefaultReturn(_) => ("-> ", " "), - _ => ("", ""), - }; - let suggestion = match should_wrap_expr { - Some(end_span) => vec![ - (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post)), - (end_span, " }".to_string()), - ], - None => vec![(data.span(), format!("{}{}{}", arrow, ty_info, post))], - }; - diag.multipart_suggestion_verbose( - fluent::infer::source_kind_closure_return, - suggestion, - rustc_errors::Applicability::HasPlaceholders, - ); - } - } - } -} - -pub enum RegionOriginNote<'a> { - Plain { - span: Span, - msg: DiagnosticMessage, - }, - WithName { - span: Span, - msg: DiagnosticMessage, - name: &'a str, - continues: bool, - }, - WithRequirement { - span: Span, - requirement: ObligationCauseAsDiagArg<'a>, - expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>, - }, -} - -impl AddSubdiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { - let mut label_or_note = |span, msg: DiagnosticMessage| { - let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); - let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); - let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); - if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { - diag.span_label(span, msg); - } else if span_is_primary && expanded_sub_count == 0 { - diag.note(msg); - } else { - diag.span_note(span, msg); - } - }; - match self { - RegionOriginNote::Plain { span, msg } => { - label_or_note(span, msg); - } - RegionOriginNote::WithName { span, msg, name, continues } => { - label_or_note(span, msg); - diag.set_arg("name", name); - diag.set_arg("continues", continues); - } - RegionOriginNote::WithRequirement { - span, - requirement, - expected_found: Some((expected, found)), - } => { - label_or_note(span, fluent::infer::subtype); - diag.set_arg("requirement", requirement); - - diag.note_expected_found(&"", expected, &"", found); - } - RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => { - // FIXME: this really should be handled at some earlier stage. Our - // handling of region checking when type errors are present is - // *terrible*. - label_or_note(span, fluent::infer::subtype_2); - diag.set_arg("requirement", requirement); - } - }; - } -} diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs new file mode 100644 index 00000000000..d232a186462 --- /dev/null +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -0,0 +1,499 @@ +use hir::GenericParamKind; +use rustc_errors::{ + fluent, AddSubdiagnostic, Applicability, DiagnosticMessage, DiagnosticStyledString, MultiSpan, +}; +use rustc_hir as hir; +use rustc_hir::{FnRetTy, Ty}; +use rustc_macros::SessionDiagnostic; +use rustc_middle::ty::{Region, TyCtxt}; +use rustc_span::symbol::kw; +use rustc_span::{symbol::Ident, BytePos, Span}; + +use crate::infer::error_reporting::{ + need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, + ObligationCauseAsDiagArg, +}; + +pub mod note_and_explain; + +#[derive(SessionDiagnostic)] +#[diag(infer::opaque_hidden_type)] +pub struct OpaqueHiddenTypeDiag { + #[primary_span] + #[label] + pub span: Span, + #[note(infer::opaque_type)] + pub opaque_type: Span, + #[note(infer::hidden_type)] + pub hidden_type: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0282")] +pub struct AnnotationRequired<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option<Span>, + #[subdiagnostic] + pub bad_label: Option<InferenceBadError<'a>>, + #[subdiagnostic] + pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, + #[subdiagnostic] + pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, +} + +// Copy of `AnnotationRequired` for E0283 +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0283")] +pub struct AmbigousImpl<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option<Span>, + #[subdiagnostic] + pub bad_label: Option<InferenceBadError<'a>>, + #[subdiagnostic] + pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, + #[subdiagnostic] + pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, +} + +// Copy of `AnnotationRequired` for E0284 +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0284")] +pub struct AmbigousReturn<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option<Span>, + #[subdiagnostic] + pub bad_label: Option<InferenceBadError<'a>>, + #[subdiagnostic] + pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, + #[subdiagnostic] + pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::need_type_info_in_generator, code = "E0698")] +pub struct NeedTypeInfoInGenerator<'a> { + #[primary_span] + pub span: Span, + pub generator_kind: GeneratorKindAsDiagArg, + #[subdiagnostic] + pub bad_label: InferenceBadError<'a>, +} + +// Used when a better one isn't available +#[derive(SessionSubdiagnostic)] +#[label(infer::label_bad)] +pub struct InferenceBadError<'a> { + #[primary_span] + pub span: Span, + pub bad_kind: &'static str, + pub prefix_kind: UnderspecifiedArgKind, + pub has_parent: bool, + pub prefix: &'a str, + pub parent_prefix: &'a str, + pub parent_name: String, + pub name: String, +} + +#[derive(SessionSubdiagnostic)] +pub enum SourceKindSubdiag<'a> { + #[suggestion_verbose( + infer::source_kind_subdiag_let, + code = ": {type_name}", + applicability = "has-placeholders" + )] + LetLike { + #[primary_span] + span: Span, + name: String, + type_name: String, + kind: &'static str, + x_kind: &'static str, + prefix_kind: UnderspecifiedArgKind, + prefix: &'a str, + arg_name: String, + }, + #[label(infer::source_kind_subdiag_generic_label)] + GenericLabel { + #[primary_span] + span: Span, + is_type: bool, + param_name: String, + parent_exists: bool, + parent_prefix: String, + parent_name: String, + }, + #[suggestion_verbose( + infer::source_kind_subdiag_generic_suggestion, + code = "::<{args}>", + applicability = "has-placeholders" + )] + GenericSuggestion { + #[primary_span] + span: Span, + arg_count: usize, + args: String, + }, +} + +#[derive(SessionSubdiagnostic)] +pub enum SourceKindMultiSuggestion<'a> { + #[multipart_suggestion_verbose( + infer::source_kind_fully_qualified, + applicability = "has-placeholders" + )] + FullyQualified { + #[suggestion_part(code = "{def_path}({adjustment}")] + span_lo: Span, + #[suggestion_part(code = "{successor_pos}")] + span_hi: Span, + def_path: String, + adjustment: &'a str, + successor_pos: &'a str, + }, + #[multipart_suggestion_verbose( + infer::source_kind_closure_return, + applicability = "has-placeholders" + )] + ClosureReturn { + #[suggestion_part(code = "{start_span_code}")] + start_span: Span, + start_span_code: String, + #[suggestion_part(code = " }}")] + end_span: Option<Span>, + }, +} + +impl<'a> SourceKindMultiSuggestion<'a> { + pub fn new_fully_qualified( + span: Span, + def_path: String, + adjustment: &'a str, + successor: (&'a str, BytePos), + ) -> Self { + Self::FullyQualified { + span_lo: span.shrink_to_lo(), + span_hi: span.shrink_to_hi().with_hi(successor.1), + def_path, + adjustment, + successor_pos: successor.0, + } + } + + pub fn new_closure_return( + ty_info: String, + data: &'a FnRetTy<'a>, + should_wrap_expr: Option<Span>, + ) -> Self { + let (arrow, post) = match data { + FnRetTy::DefaultReturn(_) => ("-> ", " "), + _ => ("", ""), + }; + let (start_span, start_span_code, end_span) = match should_wrap_expr { + Some(end_span) => { + (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post), Some(end_span)) + } + None => (data.span(), format!("{}{}{}", arrow, ty_info, post), None), + }; + Self::ClosureReturn { start_span, start_span_code, end_span } + } +} + +pub enum RegionOriginNote<'a> { + Plain { + span: Span, + msg: DiagnosticMessage, + }, + WithName { + span: Span, + msg: DiagnosticMessage, + name: &'a str, + continues: bool, + }, + WithRequirement { + span: Span, + requirement: ObligationCauseAsDiagArg<'a>, + expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>, + }, +} + +impl AddSubdiagnostic for RegionOriginNote<'_> { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut label_or_note = |span, msg: DiagnosticMessage| { + let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); + let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); + let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); + if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { + diag.span_label(span, msg); + } else if span_is_primary && expanded_sub_count == 0 { + diag.note(msg); + } else { + diag.span_note(span, msg); + } + }; + match self { + RegionOriginNote::Plain { span, msg } => { + label_or_note(span, msg); + } + RegionOriginNote::WithName { span, msg, name, continues } => { + label_or_note(span, msg); + diag.set_arg("name", name); + diag.set_arg("continues", continues); + } + RegionOriginNote::WithRequirement { + span, + requirement, + expected_found: Some((expected, found)), + } => { + label_or_note(span, fluent::infer::subtype); + diag.set_arg("requirement", requirement); + + diag.note_expected_found(&"", expected, &"", found); + } + RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => { + // FIXME: this really should be handled at some earlier stage. Our + // handling of region checking when type errors are present is + // *terrible*. + label_or_note(span, fluent::infer::subtype_2); + diag.set_arg("requirement", requirement); + } + }; + } +} + +pub enum LifetimeMismatchLabels { + InRet { + param_span: Span, + ret_span: Span, + span: Span, + label_var1: Option<Ident>, + }, + Normal { + hir_equal: bool, + ty_sup: Span, + ty_sub: Span, + span: Span, + sup: Option<Ident>, + sub: Option<Ident>, + }, +} + +impl AddSubdiagnostic for LifetimeMismatchLabels { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self { + LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { + diag.span_label(param_span, fluent::infer::declared_different); + diag.span_label(ret_span, fluent::infer::nothing); + diag.span_label(span, fluent::infer::data_returned); + diag.set_arg("label_var1_exists", label_var1.is_some()); + diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); + } + LifetimeMismatchLabels::Normal { + hir_equal, + ty_sup, + ty_sub, + span, + sup: label_var1, + sub: label_var2, + } => { + if hir_equal { + diag.span_label(ty_sup, fluent::infer::declared_multiple); + diag.span_label(ty_sub, fluent::infer::nothing); + diag.span_label(span, fluent::infer::data_lifetime_flow); + } else { + diag.span_label(ty_sup, fluent::infer::types_declared_different); + diag.span_label(ty_sub, fluent::infer::nothing); + diag.span_label(span, fluent::infer::data_flows); + diag.set_arg("label_var1_exists", label_var1.is_some()); + diag.set_arg( + "label_var1", + label_var1.map(|x| x.to_string()).unwrap_or_default(), + ); + diag.set_arg("label_var2_exists", label_var2.is_some()); + diag.set_arg( + "label_var2", + label_var2.map(|x| x.to_string()).unwrap_or_default(), + ); + } + } + } + } +} + +pub struct AddLifetimeParamsSuggestion<'a> { + pub tcx: TyCtxt<'a>, + pub sub: Region<'a>, + pub ty_sup: &'a Ty<'a>, + pub ty_sub: &'a Ty<'a>, + pub add_note: bool, +} + +impl AddSubdiagnostic for AddLifetimeParamsSuggestion<'_> { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut mk_suggestion = || { + let ( + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, + ) = (self.ty_sub, self.ty_sup) else { + return false; + }; + + if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() { + return false; + }; + + let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else { + return false; + }; + + let hir_id = self.tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); + + let node = self.tcx.hir().get(hir_id); + let is_impl = matches!(&node, hir::Node::ImplItem(_)); + let generics = match node { + hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Fn(_, ref generics, ..), + .. + }) + | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. }) + | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics, + _ => return false, + }; + + let suggestion_param_name = generics + .params + .iter() + .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) + .map(|p| p.name.ident().name) + .find(|i| *i != kw::UnderscoreLifetime); + let introduce_new = suggestion_param_name.is_none(); + let suggestion_param_name = + suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned()); + + debug!(?lifetime_sup.span); + debug!(?lifetime_sub.span); + let make_suggestion = |span: rustc_span::Span| { + if span.is_empty() { + (span, format!("{}, ", suggestion_param_name)) + } else if let Ok("&") = self.tcx.sess.source_map().span_to_snippet(span).as_deref() + { + (span.shrink_to_hi(), format!("{} ", suggestion_param_name)) + } else { + (span, suggestion_param_name.clone()) + } + }; + let mut suggestions = + vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)]; + + if introduce_new { + let new_param_suggestion = if let Some(first) = + generics.params.iter().find(|p| !p.name.ident().span.is_empty()) + { + (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name)) + } else { + (generics.span, format!("<{}>", suggestion_param_name)) + }; + + suggestions.push(new_param_suggestion); + } + + diag.multipart_suggestion( + fluent::infer::lifetime_param_suggestion, + suggestions, + Applicability::MaybeIncorrect, + ); + diag.set_arg("is_impl", is_impl); + true + }; + if mk_suggestion() && self.add_note { + diag.note(fluent::infer::lifetime_param_suggestion_elided); + } + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::lifetime_mismatch, code = "E0623")] +pub struct LifetimeMismatch<'a> { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub labels: LifetimeMismatchLabels, + #[subdiagnostic] + pub suggestion: AddLifetimeParamsSuggestion<'a>, +} + +pub struct IntroducesStaticBecauseUnmetLifetimeReq { + pub unmet_requirements: MultiSpan, + pub binding_span: Span, +} + +impl AddSubdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { + fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { + self.unmet_requirements + .push_span_label(self.binding_span, fluent::infer::msl_introduces_static); + diag.span_note(self.unmet_requirements, fluent::infer::msl_unmet_req); + } +} + +pub struct ImplNote { + pub impl_span: Option<Span>, +} + +impl AddSubdiagnostic for ImplNote { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self.impl_span { + Some(span) => diag.span_note(span, fluent::infer::msl_impl_note), + None => diag.note(fluent::infer::msl_impl_note), + }; + } +} + +pub enum TraitSubdiag { + Note { span: Span }, + Sugg { span: Span }, +} + +// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support +impl AddSubdiagnostic for TraitSubdiag { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self { + TraitSubdiag::Note { span } => { + diag.span_note(span, "this has an implicit `'static` lifetime requirement"); + } + TraitSubdiag::Sugg { span } => { + diag.span_suggestion_verbose( + span, + "consider relaxing the implicit `'static` requirement", + " + '_".to_owned(), + rustc_errors::Applicability::MaybeIncorrect, + ); + } + } + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::mismatched_static_lifetime)] +pub struct MismatchedStaticLifetime<'a> { + #[primary_span] + pub cause_span: Span, + #[subdiagnostic] + pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq, + #[subdiagnostic] + pub expl: Option<note_and_explain::RegionExplanation<'a>>, + #[subdiagnostic] + pub impl_note: ImplNote, + #[subdiagnostic] + pub trait_subdiags: Vec<TraitSubdiag>, +} diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs new file mode 100644 index 00000000000..6f1f9522c86 --- /dev/null +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -0,0 +1,179 @@ +use crate::infer::error_reporting::nice_region_error::find_anon_type; +use rustc_errors::{self, fluent, AddSubdiagnostic, IntoDiagnosticArg}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::{symbol::kw, Span}; + +#[derive(Default)] +struct DescriptionCtx<'a> { + span: Option<Span>, + kind: &'a str, + arg: String, + num_arg: u32, +} + +impl<'a> DescriptionCtx<'a> { + fn new<'tcx>( + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, + alt_span: Option<Span>, + ) -> Option<Self> { + let mut me = DescriptionCtx::default(); + me.span = alt_span; + match *region { + ty::ReEarlyBound(_) | ty::ReFree(_) => { + return Self::from_early_bound_and_free_regions(tcx, region); + } + ty::ReStatic => { + me.kind = "restatic"; + } + + ty::ReEmpty(ty::UniverseIndex::ROOT) => me.kind = "reempty", + + ty::ReEmpty(ui) => { + me.kind = "reemptyuni"; + me.arg = format!("{:?}", ui); + } + + ty::RePlaceholder(_) => return None, + + // FIXME(#13998) RePlaceholder should probably print like + // ReFree rather than dumping Debug output on the user. + // + // We shouldn't really be having unification failures with ReVar + // and ReLateBound though. + ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + me.kind = "revar"; + me.arg = format!("{:?}", region); + } + }; + Some(me) + } + + fn from_early_bound_and_free_regions<'tcx>( + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, + ) -> Option<Self> { + let mut me = DescriptionCtx::default(); + let scope = region.free_region_binding_scope(tcx).expect_local(); + match *region { + ty::ReEarlyBound(ref br) => { + let mut sp = tcx.def_span(scope); + if let Some(param) = + tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) + { + sp = param.span; + } + if br.has_name() { + me.kind = "as_defined"; + me.arg = br.name.to_string(); + } else { + me.kind = "as_defined_anon"; + }; + me.span = Some(sp) + } + ty::ReFree(ref fr) => { + if !fr.bound_region.is_named() + && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) + { + me.kind = "defined_here"; + me.span = Some(ty.span); + } else { + match fr.bound_region { + ty::BoundRegionKind::BrNamed(_, name) => { + let mut sp = tcx.def_span(scope); + if let Some(param) = + tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) + { + sp = param.span; + } + if name == kw::UnderscoreLifetime { + me.kind = "as_defined_anon"; + } else { + me.kind = "as_defined"; + me.arg = name.to_string(); + }; + me.span = Some(sp); + } + ty::BrAnon(idx) => { + me.kind = "anon_num_here"; + me.num_arg = idx+1; + me.span = Some(tcx.def_span(scope)); + }, + _ => { + me.kind = "defined_here_reg"; + me.arg = region.to_string(); + me.span = Some(tcx.def_span(scope)); + }, + } + } + } + _ => bug!(), + } + Some(me) + } + + fn add_to(self, diag: &mut rustc_errors::Diagnostic) { + diag.set_arg("desc_kind", self.kind); + diag.set_arg("desc_arg", self.arg); + diag.set_arg("desc_num_arg", self.num_arg); + } +} + +pub enum PrefixKind { + Empty, +} + +pub enum SuffixKind { + Continues, +} + +impl IntoDiagnosticArg for PrefixKind { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + let kind = match self { + Self::Empty => "empty", + } + .into(); + rustc_errors::DiagnosticArgValue::Str(kind) + } +} + +impl IntoDiagnosticArg for SuffixKind { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + let kind = match self { + Self::Continues => "continues", + } + .into(); + rustc_errors::DiagnosticArgValue::Str(kind) + } +} + +pub struct RegionExplanation<'a> { + desc: DescriptionCtx<'a>, + prefix: PrefixKind, + suffix: SuffixKind, +} + +impl RegionExplanation<'_> { + pub fn new<'tcx>( + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, + alt_span: Option<Span>, + prefix: PrefixKind, + suffix: SuffixKind, + ) -> Option<Self> { + Some(Self { desc: DescriptionCtx::new(tcx, region, alt_span)?, prefix, suffix }) + } +} + +impl AddSubdiagnostic for RegionExplanation<'_> { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + if let Some(span) = self.desc.span { + diag.span_note(span, fluent::infer::region_explanation); + } else { + diag.note(fluent::infer::region_explanation); + } + self.desc.add_to(diag); + diag.set_arg("pref_kind", self.prefix); + diag.set_arg("suff_kind", self.suffix); + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6dad9873d61..0196bd26217 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1586,28 +1586,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Some(values) => { let values = self.resolve_vars_if_possible(values); let (is_simple_error, exp_found) = match values { - ValuePairs::Terms(infer::ExpectedFound { - expected: ty::Term::Ty(expected), - found: ty::Term::Ty(found), - }) => { - let is_simple_err = expected.is_simple_text() && found.is_simple_text(); - OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span) - .report(diag); - - ( - is_simple_err, - Mismatch::Variable(infer::ExpectedFound { expected, found }), - ) + ValuePairs::Terms(infer::ExpectedFound { expected, found }) => { + match (expected.unpack(), found.unpack()) { + (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { + let is_simple_err = + expected.is_simple_text() && found.is_simple_text(); + OpaqueTypesVisitor::visit_expected_found( + self.tcx, expected, found, span, + ) + .report(diag); + + ( + is_simple_err, + Mismatch::Variable(infer::ExpectedFound { expected, found }), + ) + } + (ty::TermKind::Const(_), ty::TermKind::Const(_)) => { + (false, Mismatch::Fixed("constant")) + } + _ => (false, Mismatch::Fixed("type")), + } } - ValuePairs::Terms(infer::ExpectedFound { - expected: ty::Term::Const(_), - found: ty::Term::Const(_), - }) => (false, Mismatch::Fixed("constant")), ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { (false, Mismatch::Fixed("trait")) } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), - _ => (false, Mismatch::Fixed("type")), }; let vals = match self.values_str(values) { Some((expected, found)) => Some((expected, found)), @@ -2273,11 +2276,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return None; } - Some(match (exp_found.expected, exp_found.found) { - (ty::Term::Ty(expected), ty::Term::Ty(found)) => self.cmp(expected, found), - (expected, found) => ( - DiagnosticStyledString::highlighted(expected.to_string()), - DiagnosticStyledString::highlighted(found.to_string()), + Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) { + (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found), + _ => ( + DiagnosticStyledString::highlighted(exp_found.expected.to_string()), + DiagnosticStyledString::highlighted(exp_found.found.to_string()), ), }) } @@ -2395,19 +2398,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { type_param_span: Option<(Span, bool)>, bound_kind: GenericKind<'tcx>, sub: S, + add_lt_sugg: Option<(Span, String)>, ) { let msg = "consider adding an explicit lifetime bound"; if let Some((sp, has_lifetimes)) = type_param_span { let suggestion = if has_lifetimes { format!(" + {}", sub) } else { format!(": {}", sub) }; - err.span_suggestion_verbose( - sp, - &format!("{}...", msg), - suggestion, + let mut suggestions = vec![(sp, suggestion)]; + if let Some(add_lt_sugg) = add_lt_sugg { + suggestions.push(add_lt_sugg); + } + err.multipart_suggestion_verbose( + format!("{msg}..."), + suggestions, Applicability::MaybeIncorrect, // Issue #41966 ); } else { - let consider = format!("{} `{}: {}`...", msg, bound_kind, sub,); + let consider = format!("{} `{}: {}`...", msg, bound_kind, sub); err.help(&consider); } } @@ -2423,7 +2430,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let mut sugg = vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {}", new_lt))]; - if let Some(lt) = add_lt_sugg { + if let Some(lt) = add_lt_sugg.clone() { sugg.push(lt); sugg.rotate_right(1); } @@ -2529,7 +2536,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // for the bound is not suitable for suggestions when `-Zverbose` is set because it // uses `Debug` output, so we handle it specially here so that suggestions are // always correct. - binding_suggestion(&mut err, type_param_span, bound_kind, name); + binding_suggestion(&mut err, type_param_span, bound_kind, name, None); err } @@ -2542,7 +2549,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{} may not live long enough", labeled_user_string ); - binding_suggestion(&mut err, type_param_span, bound_kind, "'static"); + binding_suggestion(&mut err, type_param_span, bound_kind, "'static", None); err } @@ -2576,7 +2583,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { new_binding_suggestion(&mut err, type_param_span); } _ => { - binding_suggestion(&mut err, type_param_span, bound_kind, new_lt); + binding_suggestion( + &mut err, + type_param_span, + bound_kind, + new_lt, + add_lt_sugg, + ); } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 232b9b11455..cb2be93589d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), TypeAnnotationNeeded::E0283 => AmbigousImpl { span, source_kind, @@ -351,7 +351,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), TypeAnnotationNeeded::E0284 => AmbigousReturn { span, source_kind, @@ -361,7 +361,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), } } @@ -511,20 +511,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => "", }; - multi_suggestions.push(SourceKindMultiSuggestion::FullyQualified { - span: receiver.span, + multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified( + receiver.span, def_path, adjustment, successor, - }); + )); } InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { let ty_info = ty_to_string(self, ty); - multi_suggestions.push(SourceKindMultiSuggestion::ClosureReturn { + multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return( ty_info, data, should_wrap_expr, - }); + )); } } match error_code { @@ -537,7 +537,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), TypeAnnotationNeeded::E0283 => AmbigousImpl { span, source_kind, @@ -547,7 +547,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), TypeAnnotationNeeded::E0284 => AmbigousReturn { span, source_kind, @@ -557,7 +557,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess), + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), } } @@ -575,7 +575,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span, generator_kind: GeneratorKindAsDiagArg(kind), } - .into_diagnostic(&self.tcx.sess.parse_sess) + .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 9a2ab3e3224..3a4320a9a8f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -1,6 +1,9 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where both the regions are anonymous. +use crate::errors::AddLifetimeParamsSuggestion; +use crate::errors::LifetimeMismatch; +use crate::errors::LifetimeMismatchLabels; use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; @@ -8,11 +11,10 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::SubregionOrigin; use crate::infer::TyCtxt; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; -use rustc_hir as hir; -use rustc_hir::{GenericParamKind, Ty}; +use rustc_errors::AddSubdiagnostic; +use rustc_errors::{Diagnostic, ErrorGuaranteed}; +use rustc_hir::Ty; use rustc_middle::ty::Region; -use rustc_span::symbol::kw; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when both the concerned regions are anonymous. @@ -98,137 +100,50 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub); - let span_label_var1 = match anon_param_sup.pat.simple_ident() { - Some(simple_ident) => format!(" from `{}`", simple_ident), - None => String::new(), - }; - - let span_label_var2 = match anon_param_sub.pat.simple_ident() { - Some(simple_ident) => format!(" into `{}`", simple_ident), - None => String::new(), - }; - debug!( "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}", sub_is_ret_type, sup_is_ret_type ); - let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - - match (sup_is_ret_type, sub_is_ret_type) { + let labels = match (sup_is_ret_type, sub_is_ret_type) { (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => { let param_span = if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span }; - - err.span_label( + LifetimeMismatchLabels::InRet { param_span, - "this parameter and the return type are declared with different lifetimes...", - ); - err.span_label(ret_span, ""); - err.span_label(span, format!("...but data{} is returned here", span_label_var1)); - } - - (None, None) => { - if ty_sup.hir_id == ty_sub.hir_id { - err.span_label(ty_sup.span, "this type is declared with multiple lifetimes..."); - err.span_label(ty_sub.span, ""); - err.span_label(span, "...but data with one lifetime flows into the other here"); - } else { - err.span_label( - ty_sup.span, - "these two types are declared with different lifetimes...", - ); - err.span_label(ty_sub.span, ""); - err.span_label( - span, - format!("...but data{} flows{} here", span_label_var1, span_label_var2), - ); + ret_span, + span, + label_var1: anon_param_sup.pat.simple_ident(), } } - } - if suggest_adding_lifetime_params(self.tcx(), sub, ty_sup, ty_sub, &mut err) { - err.note("each elided lifetime in input position becomes a distinct lifetime"); - } + (None, None) => LifetimeMismatchLabels::Normal { + hir_equal: ty_sup.hir_id == ty_sub.hir_id, + ty_sup: ty_sup.span, + ty_sub: ty_sub.span, + span, + sup: anon_param_sup.pat.simple_ident(), + sub: anon_param_sub.pat.simple_ident(), + }, + }; - let reported = err.emit(); + let suggestion = + AddLifetimeParamsSuggestion { tcx: self.tcx(), sub, ty_sup, ty_sub, add_note: true }; + let err = LifetimeMismatch { span, labels, suggestion }; + let reported = self.tcx().sess.emit_err(err); Some(reported) } } +/// Currently only used in rustc_borrowck, probably should be +/// removed in favour of public_errors::AddLifetimeParamsSuggestion pub fn suggest_adding_lifetime_params<'tcx>( tcx: TyCtxt<'tcx>, sub: Region<'tcx>, - ty_sup: &Ty<'_>, - ty_sub: &Ty<'_>, + ty_sup: &'tcx Ty<'_>, + ty_sub: &'tcx Ty<'_>, err: &mut Diagnostic, -) -> bool { - let ( - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, - ) = (ty_sub, ty_sup) else { - return false; - }; - - if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() { - return false; - }; - - let Some(anon_reg) = tcx.is_suitable_region(sub) else { - return false; - }; - - let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); - - let node = tcx.hir().get(hir_id); - let is_impl = matches!(&node, hir::Node::ImplItem(_)); - let generics = match node { - hir::Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, ref generics, ..), .. }) - | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. }) - | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics, - _ => return false, - }; - - let suggestion_param_name = generics - .params - .iter() - .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) - .map(|p| p.name.ident().name) - .find(|i| *i != kw::UnderscoreLifetime); - let introduce_new = suggestion_param_name.is_none(); - let suggestion_param_name = - suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned()); - - debug!(?lifetime_sup.span); - debug!(?lifetime_sub.span); - let make_suggestion = |span: rustc_span::Span| { - if span.is_empty() { - (span, format!("{}, ", suggestion_param_name)) - } else if let Ok("&") = tcx.sess.source_map().span_to_snippet(span).as_deref() { - (span.shrink_to_hi(), format!("{} ", suggestion_param_name)) - } else { - (span, suggestion_param_name.clone()) - } - }; - let mut suggestions = - vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)]; - - if introduce_new { - let new_param_suggestion = - if let Some(first) = generics.params.iter().find(|p| !p.name.ident().span.is_empty()) { - (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name)) - } else { - (generics.span, format!("<{}>", suggestion_param_name)) - }; - - suggestions.push(new_param_suggestion); - } - - let mut sugg = String::from("consider introducing a named lifetime parameter"); - if is_impl { - sugg.push_str(" and update trait if needed"); - } - err.multipart_suggestion(sugg, suggestions, Applicability::MaybeIncorrect); - - true +) { + let suggestion = AddLifetimeParamsSuggestion { tcx, sub, ty_sup, ty_sub, add_note: false }; + suggestion.add_to_diagnostic(err); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index c20b96cae2e..1410e2b63b0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -1,13 +1,14 @@ //! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate //! to hold. +use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq}; +use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::infer::error_reporting::note_and_explain_region; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::ObligationCauseCode; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_middle::ty::TypeVisitor; @@ -39,12 +40,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { = *parent.code() else { return None; }; - let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type"); + // FIXME: we should point at the lifetime - let mut multi_span: MultiSpan = vec![binding_span].into(); - multi_span.push_span_label(binding_span, "introduces a `'static` lifetime requirement"); - err.span_note(multi_span, "because this has an unmet lifetime requirement"); - note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span)); + let multi_span: MultiSpan = vec![binding_span].into(); + let multispan_subdiag = IntroducesStaticBecauseUnmetLifetimeReq { + unmet_requirements: multi_span, + binding_span, + }; + + let expl = note_and_explain::RegionExplanation::new( + self.tcx(), + sup, + Some(binding_span), + note_and_explain::PrefixKind::Empty, + note_and_explain::SuffixKind::Continues, + ); + let mut impl_span = None; + let mut trait_subdiags = Vec::new(); if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) { // If an impl is local, then maybe this isn't what they want. Try to // be as helpful as possible with implicit lifetimes. @@ -73,31 +85,30 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // there aren't trait objects or because none are implicit, then just // write a single note on the impl itself. - let impl_span = self.tcx().def_span(*impl_def_id); - err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); + impl_span = Some(self.tcx().def_span(*impl_def_id)); } else { // Otherwise, point at all implicit static lifetimes - err.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); for span in &traits { - err.span_note(*span, "this has an implicit `'static` lifetime requirement"); + trait_subdiags.push(TraitSubdiag::Note { span: *span }); // It would be nice to put this immediately under the above note, but they get // pushed to the end. - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_", - Applicability::MaybeIncorrect, - ); + trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() }); } } } else { // Otherwise just point out the impl. - let impl_span = self.tcx().def_span(*impl_def_id); - err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); + impl_span = Some(self.tcx().def_span(*impl_def_id)); } - let reported = err.emit(); + let err = MismatchedStaticLifetime { + cause_span: cause.span, + unmet_lifetime_reqs: multispan_subdiag, + expl, + impl_note: ImplNote { impl_span }, + trait_subdiags, + }; + let reported = self.tcx().sess.emit_err(err); Some(reported) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fe037a458a7..bbbc044b85a 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -353,12 +353,11 @@ pub enum ValuePairs<'tcx> { impl<'tcx> ValuePairs<'tcx> { pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> { - if let ValuePairs::Terms(ExpectedFound { - expected: ty::Term::Ty(expected), - found: ty::Term::Ty(found), - }) = self + if let ValuePairs::Terms(ExpectedFound { expected, found }) = self + && let Some(expected) = expected.ty() + && let Some(found) = found.ty() { - Some((*expected, *found)) + Some((expected, found)) } else { None } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c7d7ef40d9d..75233495040 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -50,13 +50,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { - debug!("param_bound(param_ty={:?})", param_ty); - // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty); + debug!(?declared_bounds_from_env); let mut param_bounds = vec![]; for declared_bound in declared_bounds_from_env { let bound_region = declared_bound.map_bound(|outlives| outlives.1); @@ -65,6 +65,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { param_bounds.push(VerifyBound::OutlivedBy(region)); } else { // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here. + debug!("found that {param_ty:?} outlives any lifetime, returning empty vector"); return VerifyBound::AllBounds(vec![]); } } @@ -72,6 +73,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Add in the default bound of fn body that applies to all in // scope type parameters: if let Some(r) = self.implicit_region_bound { + debug!("adding implicit region bound of {r:?}"); param_bounds.push(VerifyBound::OutlivedBy(r)); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index bb534a3c7af..c41b154c3e0 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -573,13 +573,24 @@ fn write_out_deps( // Account for explicitly marked-to-track files // (e.g. accessed in proc macros). let file_depinfo = sess.parse_sess.file_depinfo.borrow(); - let extra_tracked_files = file_depinfo.iter().map(|path_sym| { - let path = PathBuf::from(path_sym.as_str()); + + let normalize_path = |path: PathBuf| { let file = FileName::from(path); escape_dep_filename(&file.prefer_local().to_string()) - }); + }; + + let extra_tracked_files = + file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))); files.extend(extra_tracked_files); + // We also need to track used PGO profile files + if let Some(ref profile_instr) = sess.opts.cg.profile_use { + files.push(normalize_path(profile_instr.as_path().to_path_buf())); + } + if let Some(ref profile_sample) = sess.opts.unstable_opts.profile_sample_use { + files.push(normalize_path(profile_sample.as_path().to_path_buf())); + } + if sess.binary_dep_depinfo() { if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend { if backend.contains('.') { diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 606d8bda8aa..5c183d4091e 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,6 +1,6 @@ -use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed}; +use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed, Handler}; use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; -use rustc_session::{lint::Level, parse::ParseSess, SessionDiagnostic}; +use rustc_session::{lint::Level, SessionDiagnostic}; use rustc_span::{Span, Symbol}; #[derive(SessionDiagnostic)] @@ -122,9 +122,9 @@ pub struct CheckNameUnknown { impl SessionDiagnostic<'_> for CheckNameUnknown { fn into_diagnostic( self, - sess: &ParseSess, + handler: &Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::lint::check_name_unknown); + let mut diag = handler.struct_err(fluent::lint::check_name_unknown); diag.code(rustc_errors::error_code!(E0602)); if let Some(suggestion) = self.suggestion { diag.help(fluent::lint::help); diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 244edec2841..cf1c5945529 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -88,7 +88,7 @@ impl<'a> SessionDiagnosticDerive<'a> { { fn into_diagnostic( self, - #sess: &'__session_diagnostic_sess rustc_session::parse::ParseSess + #sess: &'__session_diagnostic_sess rustc_errors::Handler ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, G> { use rustc_errors::IntoDiagnosticArg; #implementation diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 18d0248333a..8378d2b791d 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -424,9 +424,9 @@ pub(crate) struct MultipleCandidates { impl SessionDiagnostic<'_> for MultipleCandidates { fn into_diagnostic( self, - sess: &'_ rustc_session::parse::ParseSess, + handler: &'_ rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates); + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); diag.code(error_code!(E0465)); @@ -540,9 +540,9 @@ pub struct InvalidMetadataFiles { impl SessionDiagnostic<'_> for InvalidMetadataFiles { fn into_diagnostic( self, - sess: &'_ rustc_session::parse::ParseSess, + handler: &'_ rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); diag.code(error_code!(E0786)); @@ -568,9 +568,9 @@ pub struct CannotFindCrate { impl SessionDiagnostic<'_> for CannotFindCrate { fn into_diagnostic( self, - sess: &'_ rustc_session::parse::ParseSess, + handler: &'_ rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); + let mut diag = handler.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); diag.set_arg("locator_triple", self.locator_triple.triple()); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 1e3a6bcfc7d..4064a8f9733 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -96,6 +96,7 @@ pub mod mir; pub mod thir; pub mod traits; pub mod ty; +mod values; pub mod util { pub mod bug; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f3676604bb0..753e1f4b9da 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -839,10 +839,6 @@ pub struct LocalDecl<'tcx> { pub source_info: SourceInfo, } -// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(LocalDecl<'_>, 56); - /// Extra information about a some locals that's used for diagnostics and for /// classifying variables into local variables, statics, etc, which is needed e.g. /// for unsafety checking. @@ -1317,10 +1313,6 @@ pub struct Statement<'tcx> { pub kind: StatementKind<'tcx>, } -// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(Statement<'_>, 32); - impl Statement<'_> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. @@ -1370,13 +1362,7 @@ impl Debug for Statement<'_> { write!(fmt, "Coverage::{:?} for {:?}", kind, rgn) } Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind), - CopyNonOverlapping(box crate::mir::CopyNonOverlapping { - ref src, - ref dst, - ref count, - }) => { - write!(fmt, "copy_nonoverlapping(src={:?}, dst={:?}, count={:?})", src, dst, count) - } + Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), Nop => write!(fmt, "nop"), } } @@ -1478,7 +1464,9 @@ impl<'tcx> Place<'tcx> { /// It's guaranteed to be in the first place pub fn has_deref(&self) -> bool { // To make sure this is not accidently used in wrong mir phase - debug_assert!(!self.projection[1..].contains(&PlaceElem::Deref)); + debug_assert!( + self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref) + ); self.projection.first() == Some(&PlaceElem::Deref) } @@ -2900,3 +2888,17 @@ impl Location { } } } + +// 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::*; + use rustc_data_structures::static_assert_size; + // These are in alphabetical order, which is easy to maintain. + static_assert_size!(BasicBlockData<'_>, 144); + static_assert_size!(LocalDecl<'_>, 56); + static_assert_size!(Statement<'_>, 32); + static_assert_size!(StatementKind<'_>, 16); + static_assert_size!(Terminator<'_>, 112); + static_assert_size!(TerminatorKind<'_>, 96); +} diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 6e64a3b80c1..4e06d91012c 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -249,7 +249,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str { Retag(..) => "Retag", AscribeUserType(..) => "AscribeUserType", Coverage(..) => "Coverage", - CopyNonOverlapping(..) => "CopyNonOverlapping", + Intrinsic(..) => "Intrinsic", Nop => "Nop", } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index d7b9d59eced..e149535bec7 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -327,6 +327,34 @@ pub enum StatementKind<'tcx> { /// executed. Coverage(Box<Coverage>), + /// Denotes a call to an intrinsic that does not require an unwind path and always returns. + /// This avoids adding a new block and a terminator for simple intrinsics. + Intrinsic(Box<NonDivergingIntrinsic<'tcx>>), + + /// No-op. Useful for deleting instructions without affecting statement indices. + Nop, +} + +#[derive( + Clone, + TyEncodable, + TyDecodable, + Debug, + PartialEq, + Hash, + HashStable, + TypeFoldable, + TypeVisitable +)] +pub enum NonDivergingIntrinsic<'tcx> { + /// Denotes a call to the intrinsic function `assume`. + /// + /// The operand must be a boolean. Optimizers may use the value of the boolean to backtrack its + /// computation to infer information about other variables. So if the boolean came from a + /// `x < y` operation, subsequent operations on `x` and `y` could elide various bound checks. + /// If the argument is `false`, this operation is equivalent to `TerminatorKind::Unreachable`. + Assume(Operand<'tcx>), + /// Denotes a call to the intrinsic function `copy_nonoverlapping`. /// /// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer, @@ -340,10 +368,18 @@ pub enum StatementKind<'tcx> { /// /// **Needs clarification**: Is this typed or not, ie is there a typed load and store involved? /// I vaguely remember Ralf saying somewhere that he thought it should not be. - CopyNonOverlapping(Box<CopyNonOverlapping<'tcx>>), + CopyNonOverlapping(CopyNonOverlapping<'tcx>), +} - /// No-op. Useful for deleting instructions without affecting statement indices. - Nop, +impl std::fmt::Display for NonDivergingIntrinsic<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Assume(op) => write!(f, "assume({op:?})"), + Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => { + write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})") + } + } + } } /// Describes what kind of retag is to be performed. @@ -1195,7 +1231,8 @@ pub enum BinOp { mod size_asserts { use super::*; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(AggregateKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(AggregateKind<'_>, 40); static_assert_size!(Operand<'_>, 24); static_assert_size!(Place<'_>, 16); static_assert_size!(PlaceElem<'_>, 24); diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 7bd65f42e3f..708ea4398c8 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -425,14 +425,15 @@ macro_rules! make_mir_visitor { location ) } - StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{ - src, - dst, - count, - }) => { - self.visit_operand(src, location); - self.visit_operand(dst, location); - self.visit_operand(count, location) + StatementKind::Intrinsic(box ref $($mutability)? intrinsic) => { + match intrinsic { + NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location), + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => { + self.visit_operand(src, location); + self.visit_operand(dst, location); + self.visit_operand(count, location); + } + } } StatementKind::Nop => {} } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 59e14337f4e..c50f8b0eebe 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts}; use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; @@ -695,17 +695,32 @@ impl<'tcx> fmt::Display for Pat<'tcx> { Ok(()) } PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { - let variant = match self.kind { - PatKind::Variant { adt_def, variant_index, .. } => { - Some(adt_def.variant(variant_index)) - } - _ => self.ty.ty_adt_def().and_then(|adt| { - if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None } + let variant_and_name = match self.kind { + PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| { + let variant = adt_def.variant(variant_index); + let adt_did = adt_def.did(); + let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did) + || tcx.get_diagnostic_item(sym::Result) == Some(adt_did) + { + variant.name.to_string() + } else { + format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name) + }; + Some((variant, name)) + }), + _ => self.ty.ty_adt_def().and_then(|adt_def| { + if !adt_def.is_enum() { + ty::tls::with(|tcx| { + Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did()))) + }) + } else { + None + } }), }; - if let Some(variant) = variant { - write!(f, "{}", variant.name)?; + if let Some((variant, name)) = &variant_and_name { + write!(f, "{}", name)?; // Only for Adt we can have `S {...}`, // which we handle separately here. @@ -730,8 +745,9 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } } - let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len()); - if num_fields != 0 || variant.is_none() { + let num_fields = + variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len()); + if num_fields != 0 || variant_and_name.is_none() { write!(f, "(")?; for i in 0..num_fields { write!(f, "{}", start_or_comma())?; @@ -809,8 +825,12 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 72); - static_assert_size!(PatKind<'_>, 56); - static_assert_size!(Stmt<'_>, 56); - static_assert_size!(StmtKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(Pat<'_>, 64); + #[cfg(not(bootstrap))] + static_assert_size!(PatKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(Stmt<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(StmtKind<'_>, 40); } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ea6bb8a7abd..c22c899c5cc 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -1,5 +1,5 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, InferConst, Term, Ty, TypeFlags}; +use crate::ty::{self, InferConst, Ty, TypeFlags}; use std::slice; #[derive(Debug)] @@ -243,9 +243,9 @@ impl FlagComputation { } ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { self.add_projection_ty(projection_ty); - match term { - Term::Ty(ty) => self.add_ty(ty), - Term::Const(c) => self.add_const(c), + match term.unpack() { + ty::TermKind::Ty(ty) => self.add_ty(ty), + ty::TermKind::Const(c) => self.add_const(c), } } ty::PredicateKind::WellFormed(arg) => { @@ -320,9 +320,9 @@ impl FlagComputation { fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); - match projection.term { - ty::Term::Ty(ty) => self.add_ty(ty), - ty::Term::Const(ct) => self.add_const(ct), + match projection.term.unpack() { + ty::TermKind::Ty(ty) => self.add_ty(ty), + ty::TermKind::Const(ct) => self.add_const(ct), } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index a1d980af921..8631ee91fa4 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -328,6 +328,7 @@ impl<'tcx> GenericPredicates<'tcx> { } } + #[instrument(level = "debug", skip(self, tcx))] fn instantiate_into( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2c587b76f02..abb7ddd88b1 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -22,7 +22,7 @@ use rustc_target::abi::call::{ use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; -use std::cmp; +use std::cmp::{self, Ordering}; use std::fmt; use std::iter; use std::num::NonZeroUsize; @@ -1046,131 +1046,191 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // that allow representation optimization.) assert!(def.is_enum()); - // The current code for niche-filling relies on variant indices - // instead of actual discriminants, so dataful enums with - // explicit discriminants (RFC #2363) would misbehave. - let no_explicit_discriminants = def - .variants() - .iter_enumerated() - .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32())); - - let mut niche_filling_layout = None; - - // Niche-filling enum optimization. - if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants { - let mut dataful_variant = None; - let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); + // Until we've decided whether to use the tagged or + // niche filling LayoutS, we don't want to intern the + // variant layouts, so we can't store them in the + // overall LayoutS. Store the overall LayoutS + // and the variant LayoutSs here until then. + struct TmpLayout<'tcx> { + layout: LayoutS<'tcx>, + variants: IndexVec<VariantIdx, LayoutS<'tcx>>, + } - // Find one non-ZST variant. - 'variants: for (v, fields) in variants.iter_enumerated() { - if absent(fields) { - continue 'variants; + let calculate_niche_filling_layout = + || -> Result<Option<TmpLayout<'tcx>>, LayoutError<'tcx>> { + // The current code for niche-filling relies on variant indices + // instead of actual discriminants, so enums with + // explicit discriminants (RFC #2363) would misbehave. + if def.repr().inhibit_enum_layout_opt() + || def + .variants() + .iter_enumerated() + .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())) + { + return Ok(None); } - for f in fields { - if !f.is_zst() { - if dataful_variant.is_none() { - dataful_variant = Some(v); - continue 'variants; - } else { - dataful_variant = None; - break 'variants; - } - } + + if variants.len() < 2 { + return Ok(None); } - niche_variants = *niche_variants.start().min(&v)..=v; - } - if niche_variants.start() > niche_variants.end() { - dataful_variant = None; - } + let mut align = dl.aggregate_align; + let mut variant_layouts = variants + .iter_enumerated() + .map(|(j, v)| { + let mut st = self.univariant_uninterned( + ty, + v, + &def.repr(), + StructKind::AlwaysSized, + )?; + st.variants = Variants::Single { index: j }; + + align = align.max(st.align); + + Ok(st) + }) + .collect::<Result<IndexVec<VariantIdx, _>, _>>()?; + + let largest_variant_index = match variant_layouts + .iter_enumerated() + .max_by_key(|(_i, layout)| layout.size.bytes()) + .map(|(i, _layout)| i) + { + None => return Ok(None), + Some(i) => i, + }; - if let Some(i) = dataful_variant { - let count = (niche_variants.end().as_u32() - - niche_variants.start().as_u32() - + 1) as u128; + let all_indices = VariantIdx::new(0)..=VariantIdx::new(variants.len() - 1); + let needs_disc = |index: VariantIdx| { + index != largest_variant_index && !absent(&variants[index]) + }; + let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() + ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); + + let count = niche_variants.size_hint().1.unwrap() as u128; // Find the field with the largest niche - let niche_candidate = variants[i] + let (field_index, niche, (niche_start, niche_scalar)) = match variants + [largest_variant_index] .iter() .enumerate() .filter_map(|(j, field)| Some((j, field.largest_niche?))) - .max_by_key(|(_, niche)| niche.available(dl)); - - if let Some((field_index, niche, (niche_start, niche_scalar))) = - niche_candidate.and_then(|(field_index, niche)| { - Some((field_index, niche, niche.reserve(self, count)?)) - }) + .max_by_key(|(_, niche)| niche.available(dl)) + .and_then(|(j, niche)| Some((j, niche, niche.reserve(self, count)?))) { - let mut align = dl.aggregate_align; - let st = variants - .iter_enumerated() - .map(|(j, v)| { - let mut st = self.univariant_uninterned( - ty, - v, - &def.repr(), - StructKind::AlwaysSized, - )?; - st.variants = Variants::Single { index: j }; + None => return Ok(None), + Some(x) => x, + }; - align = align.max(st.align); + let niche_offset = niche.offset + + variant_layouts[largest_variant_index].fields.offset(field_index); + let niche_size = niche.value.size(dl); + let size = variant_layouts[largest_variant_index].size.align_to(align.abi); - Ok(tcx.intern_layout(st)) - }) - .collect::<Result<IndexVec<VariantIdx, _>, _>>()?; + let all_variants_fit = + variant_layouts.iter_enumerated_mut().all(|(i, layout)| { + if i == largest_variant_index { + return true; + } - let offset = st[i].fields().offset(field_index) + niche.offset; + layout.largest_niche = None; - // Align the total size to the largest alignment. - let size = st[i].size().align_to(align.abi); + if layout.size <= niche_offset { + // This variant will fit before the niche. + return true; + } - let abi = if st.iter().all(|v| v.abi().is_uninhabited()) { - Abi::Uninhabited - } else if align == st[i].align() && size == st[i].size() { - // When the total alignment and size match, we can use the - // same ABI as the scalar variant with the reserved niche. - match st[i].abi() { - Abi::Scalar(_) => Abi::Scalar(niche_scalar), - Abi::ScalarPair(first, second) => { - // Only the niche is guaranteed to be initialised, - // so use union layout for the other primitive. - if offset.bytes() == 0 { - Abi::ScalarPair(niche_scalar, second.to_union()) - } else { - Abi::ScalarPair(first.to_union(), niche_scalar) + // Determine if it'll fit after the niche. + let this_align = layout.align.abi; + let this_offset = (niche_offset + niche_size).align_to(this_align); + + if this_offset + layout.size > size { + return false; + } + + // It'll fit, but we need to make some adjustments. + match layout.fields { + FieldsShape::Arbitrary { ref mut offsets, .. } => { + for (j, offset) in offsets.iter_mut().enumerate() { + if !variants[i][j].is_zst() { + *offset += this_offset; + } } } - _ => Abi::Aggregate { sized: true }, + _ => { + panic!("Layout of fields should be Arbitrary for variants") + } } - } else { - Abi::Aggregate { sized: true } - }; - let largest_niche = Niche::from_scalar(dl, offset, niche_scalar); - - niche_filling_layout = Some(LayoutS { - variants: Variants::Multiple { - tag: niche_scalar, - tag_encoding: TagEncoding::Niche { - dataful_variant: i, - niche_variants, - niche_start, - }, - tag_field: 0, - variants: st, - }, - fields: FieldsShape::Arbitrary { - offsets: vec![offset], - memory_index: vec![0], - }, - abi, - largest_niche, - size, - align, + // It can't be a Scalar or ScalarPair because the offset isn't 0. + if !layout.abi.is_uninhabited() { + layout.abi = Abi::Aggregate { sized: true }; + } + layout.size += this_offset; + + true }); + + if !all_variants_fit { + return Ok(None); } - } - } + + let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar); + + let others_zst = variant_layouts.iter_enumerated().all(|(i, layout)| { + i == largest_variant_index || layout.size == Size::ZERO + }); + let same_size = size == variant_layouts[largest_variant_index].size; + let same_align = align == variant_layouts[largest_variant_index].align; + + let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) { + Abi::Uninhabited + } else if same_size && same_align && others_zst { + match variant_layouts[largest_variant_index].abi { + // When the total alignment and size match, we can use the + // same ABI as the scalar variant with the reserved niche. + Abi::Scalar(_) => Abi::Scalar(niche_scalar), + Abi::ScalarPair(first, second) => { + // Only the niche is guaranteed to be initialised, + // so use union layouts for the other primitive. + if niche_offset == Size::ZERO { + Abi::ScalarPair(niche_scalar, second.to_union()) + } else { + Abi::ScalarPair(first.to_union(), niche_scalar) + } + } + _ => Abi::Aggregate { sized: true }, + } + } else { + Abi::Aggregate { sized: true } + }; + + let layout = LayoutS { + variants: Variants::Multiple { + tag: niche_scalar, + tag_encoding: TagEncoding::Niche { + untagged_variant: largest_variant_index, + niche_variants, + niche_start, + }, + tag_field: 0, + variants: IndexVec::new(), + }, + fields: FieldsShape::Arbitrary { + offsets: vec![niche_offset], + memory_index: vec![0], + }, + abi, + largest_niche, + size, + align, + }; + + Ok(Some(TmpLayout { layout, variants: variant_layouts })) + }; + + let niche_filling_layout = calculate_niche_filling_layout()?; let (mut min, mut max) = (i128::MAX, i128::MIN); let discr_type = def.repr().discr_type(); @@ -1425,15 +1485,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); - let layout_variants = - layout_variants.into_iter().map(|v| tcx.intern_layout(v)).collect(); - let tagged_layout = LayoutS { variants: Variants::Multiple { tag, tag_encoding: TagEncoding::Direct, tag_field: 0, - variants: layout_variants, + variants: IndexVec::new(), }, fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], @@ -1445,20 +1502,45 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size, }; - let best_layout = match (tagged_layout, niche_filling_layout) { - (tagged_layout, Some(niche_filling_layout)) => { + let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; + + let mut best_layout = match (tagged_layout, niche_filling_layout) { + (tl, Some(nl)) => { // Pick the smaller layout; otherwise, // pick the layout with the larger niche; otherwise, // pick tagged as it has simpler codegen. - cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| { - let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl)); - (layout.size, cmp::Reverse(niche_size)) - }) + use Ordering::*; + let niche_size = |tmp_l: &TmpLayout<'_>| { + tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) + }; + match ( + tl.layout.size.cmp(&nl.layout.size), + niche_size(&tl).cmp(&niche_size(&nl)), + ) { + (Greater, _) => nl, + (Equal, Less) => nl, + _ => tl, + } } - (tagged_layout, None) => tagged_layout, + (tl, None) => tl, + }; + + // Now we can intern the variant layouts and store them in the enum layout. + best_layout.layout.variants = match best_layout.layout.variants { + Variants::Multiple { tag, tag_encoding, tag_field, .. } => Variants::Multiple { + tag, + tag_encoding, + tag_field, + variants: best_layout + .variants + .into_iter() + .map(|layout| tcx.intern_layout(layout)) + .collect(), + }, + _ => bug!(), }; - tcx.intern_layout(best_layout) + tcx.intern_layout(best_layout.layout) } // Types with no meaningful known layout. @@ -2559,11 +2641,11 @@ where // using more niches than just null (e.g., the first page of // the address space, or unaligned pointers). Variants::Multiple { - tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag_encoding: TagEncoding::Niche { untagged_variant, .. }, tag_field, .. } if this.fields.offset(tag_field) == offset => { - Some(this.for_variant(cx, dataful_variant)) + Some(this.for_variant(cx, untagged_variant)) } _ => Some(this), }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a3f7880b9a5..ee4e8ff50f8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -41,6 +41,7 @@ use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; +use rustc_serialize::{Decodable, Encodable}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; @@ -50,6 +51,9 @@ pub use vtable::*; use std::fmt::Debug; use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; +use std::mem; +use std::num::NonZeroUsize; use std::ops::ControlFlow; use std::{fmt, str}; @@ -459,15 +463,6 @@ pub(crate) struct TyS<'tcx> { outer_exclusive_binder: ty::DebruijnIndex, } -// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyS<'_>, 40); - -// We are actually storing a stable hash cache next to the type, so let's -// also check the full size -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(WithStableHash<TyS<'_>>, 56); - /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] @@ -524,10 +519,6 @@ pub(crate) struct PredicateS<'tcx> { outer_exclusive_binder: ty::DebruijnIndex, } -// This type is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateS<'_>, 56); - /// Use this rather than `PredicateS`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] @@ -911,42 +902,122 @@ pub struct CoercePredicate<'tcx> { } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable)] -pub enum Term<'tcx> { - Ty(Ty<'tcx>), - Const(Const<'tcx>), +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Term<'tcx> { + ptr: NonZeroUsize, + marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, } impl<'tcx> From<Ty<'tcx>> for Term<'tcx> { fn from(ty: Ty<'tcx>) -> Self { - Term::Ty(ty) + TermKind::Ty(ty).pack() } } impl<'tcx> From<Const<'tcx>> for Term<'tcx> { fn from(c: Const<'tcx>) -> Self { - Term::Const(c) + TermKind::Const(c).pack() + } +} + +impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.unpack().hash_stable(hcx, hasher); + } +} + +impl<'tcx> TypeFoldable<'tcx> for Term<'tcx> { + fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(self.unpack().try_fold_with(folder)?.pack()) + } +} + +impl<'tcx> TypeVisitable<'tcx> for Term<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.unpack().visit_with(visitor) + } +} + +impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> { + fn encode(&self, e: &mut E) { + self.unpack().encode(e) + } +} + +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> { + fn decode(d: &mut D) -> Self { + let res: TermKind<'tcx> = Decodable::decode(d); + res.pack() } } impl<'tcx> Term<'tcx> { + #[inline] + pub fn unpack(self) -> TermKind<'tcx> { + let ptr = self.ptr.get(); + // SAFETY: use of `Interned::new_unchecked` here is ok because these + // pointers were originally created from `Interned` types in `pack()`, + // and this is just going in the other direction. + unsafe { + match ptr & TAG_MASK { + TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), + ))), + CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), + ))), + _ => core::intrinsics::unreachable(), + } + } + } + pub fn ty(&self) -> Option<Ty<'tcx>> { - if let Term::Ty(ty) = self { Some(*ty) } else { None } + if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } } pub fn ct(&self) -> Option<Const<'tcx>> { - if let Term::Const(c) = self { Some(*c) } else { None } + if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } } pub fn into_arg(self) -> GenericArg<'tcx> { - match self { - Term::Ty(ty) => ty.into(), - Term::Const(c) => c.into(), + match self.unpack() { + TermKind::Ty(ty) => ty.into(), + TermKind::Const(c) => c.into(), } } } +const TAG_MASK: usize = 0b11; +const TYPE_TAG: usize = 0b00; +const CONST_TAG: usize = 0b01; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] +pub enum TermKind<'tcx> { + Ty(Ty<'tcx>), + Const(Const<'tcx>), +} + +impl<'tcx> TermKind<'tcx> { + #[inline] + fn pack(self) -> Term<'tcx> { + let (tag, ptr) = match self { + TermKind::Ty(ty) => { + // Ensure we can use the tag bits. + assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); + (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) + } + TermKind::Const(ct) => { + // Ensure we can use the tag bits. + assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); + (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize) + } + }; + + Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// @@ -2531,3 +2602,14 @@ pub struct DestructuredConst<'tcx> { pub variant: Option<VariantIdx>, pub fields: &'tcx [ty::Const<'tcx>], } + +// Some types 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::*; + use rustc_data_structures::static_assert_size; + // These are in alphabetical order, which is easy to maintain. + static_assert_size!(PredicateS<'_>, 48); + static_assert_size!(TyS<'_>, 40); + static_assert_size!(WithStableHash<TyS<'_>>, 56); +} diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 329478f27b7..1ae3063dae4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,7 +1,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{ - self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable, + self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, }; use rustc_apfloat::ieee::{Double, Single}; @@ -855,7 +855,7 @@ pub trait PrettyPrinter<'tcx>: } p!(")"); - if let Term::Ty(ty) = return_ty.skip_binder() { + if let Some(ty) = return_ty.skip_binder().ty() { if !ty.is_unit() { p!(" -> ", print(return_ty)); } @@ -942,13 +942,9 @@ pub trait PrettyPrinter<'tcx>: p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name)); - match term { - Term::Ty(ty) => { - p!(print(ty)) - } - Term::Const(c) => { - p!(print(c)); - } + match term.unpack() { + TermKind::Ty(ty) => p!(print(ty)), + TermKind::Const(c) => p!(print(c)), }; } @@ -2608,9 +2604,9 @@ define_print_and_forward_display! { } ty::Term<'tcx> { - match self { - ty::Term::Ty(ty) => p!(print(ty)), - ty::Term::Const(c) => p!(print(c)), + match self.unpack() { + ty::TermKind::Ty(ty) => p!(print(ty)), + ty::TermKind::Const(c) => p!(print(c)), } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 818affa7113..109a4df83b0 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -6,7 +6,7 @@ use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; use rustc_span::DUMMY_SP; @@ -803,15 +803,15 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { } } -impl<'tcx> Relate<'tcx> for ty::Term<'tcx> { +impl<'tcx> Relate<'tcx> for Term<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, a: Self, b: Self, ) -> RelateResult<'tcx, Self> { - Ok(match (a, b) { - (Term::Ty(a), Term::Ty(b)) => relation.relate(a, b)?.into(), - (Term::Const(a), Term::Const(b)) => relation.relate(a, b)?.into(), + Ok(match (a.unpack(), b.unpack()) { + (TermKind::Ty(a), TermKind::Ty(b)) => relation.relate(a, b)?.into(), + (TermKind::Const(a), TermKind::Const(b)) => relation.relate(a, b)?.into(), _ => return Err(TypeError::Mismatch), }) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 57555433f55..e6bd2eed565 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -7,7 +7,7 @@ use crate::mir::ProjectionKind; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; +use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; use rustc_hir as hir; use rustc_hir::def::Namespace; @@ -344,10 +344,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> { impl<'a, 'tcx> Lift<'tcx> for Term<'a> { type Lifted = ty::Term<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some(match self { - Term::Ty(ty) => Term::Ty(tcx.lift(ty)?), - Term::Const(c) => Term::Const(tcx.lift(c)?), - }) + Some( + match self.unpack() { + TermKind::Ty(ty) => TermKind::Ty(tcx.lift(ty)?), + TermKind::Const(c) => TermKind::Const(tcx.lift(c)?), + } + .pack(), + ) } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 02fe1f3a7bd..831724bc4b0 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -165,9 +165,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } }; - substs.iter().rev().chain(opt_ty.map(|term| match term { - ty::Term::Ty(ty) => ty.into(), - ty::Term::Const(ct) => ct.into(), + substs.iter().rev().chain(opt_ty.map(|term| match term.unpack() { + ty::TermKind::Ty(ty) => ty.into(), + ty::TermKind::Const(ct) => ct.into(), })) })); } diff --git a/compiler/rustc_query_impl/src/values.rs b/compiler/rustc_middle/src/values.rs index 0ed48f8d4a0..7fbe9ae2a84 100644 --- a/compiler/rustc_query_impl/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -1,39 +1,28 @@ -use super::QueryCtxt; -use rustc_middle::ty::{self, AdtSizedConstraint, Ty}; +use rustc_middle::ty::{self, AdtSizedConstraint, Ty, TyCtxt}; +use rustc_query_system::Value; -pub(super) trait Value<'tcx>: Sized { - fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self; -} - -impl<'tcx, T> Value<'tcx> for T { - default fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> T { - tcx.sess.abort_if_errors(); - bug!("Value::from_cycle_error called without errors"); - } -} - -impl<'tcx> Value<'tcx> for Ty<'_> { - fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self { +impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) } } } -impl<'tcx> Value<'tcx> for ty::SymbolName<'_> { - fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self { +impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { std::mem::transmute::<ty::SymbolName<'tcx>, ty::SymbolName<'_>>(ty::SymbolName::new( - *tcx, "<error>", + tcx, "<error>", )) } } } -impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> { - fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self { +impl<'tcx> Value<TyCtxt<'tcx>> for AdtSizedConstraint<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { // SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { @@ -44,8 +33,8 @@ impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> { } } -impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self { +impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self { let err = tcx.ty_error(); // FIXME(compiler-errors): It would be nice if we could get the // query key, so we could at least generate a fn signature that diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 319183eb9b3..115d34ff8fa 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -754,8 +754,8 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>( hir_id: HirId, witnesses: Vec<DeconstructedPat<'p, 'tcx>>, ) { - let joined_patterns = joined_uncovered_patterns(cx, &witnesses); cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| { + let joined_patterns = joined_uncovered_patterns(cx, &witnesses); let mut lint = build.build("some variants are not matched explicitly"); lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); lint.help( diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 483c1e274aa..3e08a8799ef 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { | StatementKind::Retag(..) | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => None, }; if let Some(destination) = destination { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index f6b5af90a85..18760b6c6fa 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -142,7 +142,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc | StatementKind::FakeRead(..) | StatementKind::Nop | StatementKind::Retag(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::StorageLive(..) => {} } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index c3258386223..f46fd118bde 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -330,7 +330,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 0f5fd77f7ab..beff19a3ab2 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -105,7 +105,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { // safe (at least as emitted during MIR construction) } - StatementKind::CopyNonOverlapping(..) => unreachable!(), + // Move to above list once mir construction uses it. + StatementKind::Intrinsic(..) => unreachable!(), } self.super_statement(statement, location); } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 423e78317aa..9f842c929dc 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -825,7 +825,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> // Retain spans from all other statements StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } | StatementKind::Deinit(..) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 9163672f570..3f3870cc7ba 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -52,7 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Coverage(_) - | StatementKind::CopyNonOverlapping(_) + | StatementKind::Intrinsic(_) | StatementKind::Nop => (), StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index da55510920e..9bc47613e4c 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -537,7 +537,7 @@ impl<'a> Conflicts<'a> { | StatementKind::FakeRead(..) | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index dbff4a6bd69..705cf776fb2 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1452,7 +1452,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | StatementKind::Retag(..) | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index b7ba616510c..9892580e63d 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -46,12 +46,31 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { let mut args = args.drain(..); block.statements.push(Statement { source_info: terminator.source_info, - kind: StatementKind::CopyNonOverlapping(Box::new( - rustc_middle::mir::CopyNonOverlapping { - src: args.next().unwrap(), - dst: args.next().unwrap(), - count: args.next().unwrap(), - }, + kind: StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::CopyNonOverlapping( + rustc_middle::mir::CopyNonOverlapping { + src: args.next().unwrap(), + dst: args.next().unwrap(), + count: args.next().unwrap(), + }, + ), + )), + }); + assert_eq!( + args.next(), + None, + "Extra argument for copy_non_overlapping intrinsic" + ); + drop(args); + terminator.kind = TerminatorKind::Goto { target }; + } + sym::assume => { + let target = target.unwrap(); + let mut args = args.drain(..); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::Assume(args.next().unwrap()), )), }); assert_eq!( diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 67ea5cfdb3c..67dae71468f 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -103,7 +103,7 @@ fn run_passes_inner<'tcx>( let name = pass.name(); // Gather information about what we should be doing for this pass - let overriden = + let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { trace!( pass = %name, @@ -112,7 +112,7 @@ fn run_passes_inner<'tcx>( ); *polarity }); - let is_enabled = overriden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)); + let is_enabled = overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)); let new_phase = pass.phase_change(); let dump_enabled = (is_enabled && pass.is_mir_dump_enabled()) || new_phase.is_some(); let validate = (validate && is_enabled) diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 41a0bfac41a..f1bbf2ea7e8 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -51,7 +51,7 @@ impl RemoveNoopLandingPads { StatementKind::Assign { .. } | StatementKind::SetDiscriminant { .. } | StatementKind::Deinit(..) - | StatementKind::CopyNonOverlapping(..) + | StatementKind::Intrinsic(..) | StatementKind::Retag { .. } => { return false; } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 190f9c1ac15..2f116aaa958 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -249,7 +249,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< | StatementKind::AscribeUserType(_, _) | StatementKind::Coverage(_) | StatementKind::StorageDead(_) - | StatementKind::CopyNonOverlapping(_) + | StatementKind::Intrinsic(_) | StatementKind::Nop => {} } } @@ -317,7 +317,7 @@ fn find_determining_place<'tcx>( | StatementKind::Retag(_, _) | StatementKind::AscribeUserType(_, _) | StatementKind::Coverage(_) - | StatementKind::CopyNonOverlapping(_) + | StatementKind::Intrinsic(_) | StatementKind::Nop => {} // If the discriminant is set, it is always set diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index bed48db959a..57d372fda56 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -499,7 +499,7 @@ impl UsedLocals { impl<'tcx> Visitor<'tcx> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { - StatementKind::CopyNonOverlapping(..) + StatementKind::Intrinsic(..) | StatementKind::Retag(..) | StatementKind::Coverage(..) | StatementKind::FakeRead(..) diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 77b6cfa1f69..d5f05e790d3 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -47,9 +47,10 @@ pub struct UnusedGenericParams { impl SessionDiagnostic<'_> for UnusedGenericParams { fn into_diagnostic( self, - sess: &'_ rustc_session::parse::ParseSess, + handler: &'_ rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(rustc_errors::fluent::monomorphize::unused_generic_params); + let mut diag = + handler.struct_err(rustc_errors::fluent::monomorphize::unused_generic_params); diag.set_span(self.span); for (span, name) in self.param_spans.into_iter().zip(self.param_names) { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d4828a20120..ed37ede65d5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1977,6 +1977,9 @@ impl<'a> Parser<'a> { open_delim_span: Span, ) -> PResult<'a, ()> { if self.token.kind == token::Comma { + if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) { + return Ok(()); + } let mut snapshot = self.create_snapshot_for_diagnostic(); snapshot.bump(); match snapshot.parse_seq_to_before_end( @@ -1997,7 +2000,7 @@ impl<'a> Parser<'a> { return Err(MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(self.sess)); + }.into_diagnostic(&self.sess.span_diagnostic)); } Ok(_) => (), Err(err) => err.cancel(), @@ -2745,7 +2748,8 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess)) + Err(CatchAfterTry { span: self.prev_token.span } + .into_diagnostic(&self.sess.span_diagnostic)) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index dbdd85ea8e8..b190a7062de 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1526,6 +1526,17 @@ impl<'a> Parser<'a> { if self.token == token::Comma { seen_comma = true; } + if self.eat(&token::Semi) { + let sp = self.prev_token.span; + let mut err = self.struct_span_err(sp, format!("{adt_ty} fields are separated by `,`")); + err.span_suggestion_short( + sp, + "replace `;` with `,`", + ",", + Applicability::MachineApplicable, + ); + return Err(err); + } match self.token.kind { token::Comma => { self.bump(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a63af4159e8..d0b46aa2c45 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1651,6 +1651,7 @@ impl CheckAttrVisitor<'_> { E0552, "unrecognized representation hint" ) + .help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`") .emit(); continue; diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 212ea9e57a3..3bb8c0bb48c 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -103,7 +103,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", + Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}", self.hir_map.def_path(owner).to_string_no_crate_verbose(), max, missing_items, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 8ea09880694..26d397f70e0 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -34,9 +34,6 @@ pub use rustc_query_system::query::{deadlock, QueryContext}; mod keys; use keys::Key; -mod values; -use self::values::Value; - pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 274df5b5e5e..1e375deb20d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -18,6 +18,7 @@ use rustc_query_system::query::{ force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, }; +use rustc_query_system::Value; use std::any::Any; use std::num::NonZeroU64; use thin_vec::ThinVec; @@ -174,21 +175,17 @@ impl<'tcx> QueryCtxt<'tcx> { } macro_rules! handle_cycle_error { - ([][$tcx: expr, $error:expr]) => {{ - $error.emit(); - Value::from_cycle_error($tcx) + ([]) => {{ + rustc_query_system::HandleCycleError::Error }}; - ([(fatal_cycle) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ - $error.emit(); - $tcx.sess.abort_if_errors(); - unreachable!() + ([(fatal_cycle) $($rest:tt)*]) => {{ + rustc_query_system::HandleCycleError::Fatal }}; - ([(cycle_delay_bug) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ - $error.delay_as_bug(); - Value::from_cycle_error($tcx) + ([(cycle_delay_bug) $($rest:tt)*]) => {{ + rustc_query_system::HandleCycleError::DelayBug }}; - ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - handle_cycle_error!([$($modifiers)*][$($args)*]) + ([$other:tt $($modifiers:tt)*]) => { + handle_cycle_error!([$($modifiers)*]) }; } @@ -320,6 +317,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryDescription<QueryCtxt<'tcx>>, Q::Key: DepNodeParams<TyCtxt<'tcx>>, + Q::Value: Value<TyCtxt<'tcx>>, { if let Some(key) = Q::Key::recover(tcx, &dep_node) { #[cfg(debug_assertions)] @@ -418,7 +416,7 @@ macro_rules! define_queries { depth_limit: depth_limit!([$($modifiers)*]), dep_kind: dep_graph::DepKind::$name, hash_result: hash_result!([$($modifiers)*]), - handle_cycle_error: |tcx, mut error| handle_cycle_error!([$($modifiers)*][tcx, error]), + handle_cycle_error: handle_cycle_error!([$($modifiers)*]), compute, cache_on_disk, try_load_from_disk: Self::TRY_LOAD_FROM_DISK, diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 5f992ec9e21..3fb06cbedbd 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -12,6 +12,13 @@ impl AddSubdiagnostic for CycleStack { } } +#[derive(Copy, Clone)] +pub enum HandleCycleError { + Error, + Fatal, + DelayBug, +} + #[derive(SessionSubdiagnostic)] pub enum StackCount { #[note(query_system::cycle_stack_single)] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 7067bc5f09c..8a88b5c3340 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -20,3 +20,7 @@ pub mod dep_graph; mod error; pub mod ich; pub mod query; +mod values; + +pub use error::HandleCycleError; +pub use values::Value; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index ea38df836cb..c63e110a62e 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -2,12 +2,12 @@ use crate::dep_graph::DepNode; use crate::dep_graph::SerializedDepNodeIndex; +use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::{QueryContext, QueryState}; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use std::fmt::Debug; use std::hash::Hash; @@ -19,6 +19,7 @@ pub trait QueryConfig { type Stored: Clone; } +#[derive(Copy, Clone)] pub struct QueryVTable<CTX: QueryContext, K, V> { pub anon: bool, pub dep_kind: CTX::DepKind, @@ -28,7 +29,7 @@ pub struct QueryVTable<CTX: QueryContext, K, V> { pub compute: fn(CTX::DepContext, K) -> V, pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>, - pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorGuaranteed>) -> V, + pub handle_cycle_error: HandleCycleError, pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>, } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index ddb5cd06344..45b4079fb54 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -572,7 +572,7 @@ pub(crate) fn report_cycle<'a>( stack_count, }; - cycle_diag.into_diagnostic(&sess.parse_sess) + cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic) } pub fn print_query_stack<CTX: QueryContext>( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 7bbc22e8293..e39e39860cb 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -7,6 +7,8 @@ use crate::query::caches::QueryCache; use crate::query::config::{QueryDescription, QueryVTable}; use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; +use crate::values::Value; +use crate::HandleCycleError; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; #[cfg(parallel_compiler)] @@ -118,19 +120,46 @@ where fn mk_cycle<CTX, V, R>( tcx: CTX, error: CycleError, - handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorGuaranteed>) -> V, + handler: HandleCycleError, cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>, ) -> R where CTX: QueryContext, - V: std::fmt::Debug, + V: std::fmt::Debug + Value<CTX::DepContext>, R: Clone, { let error = report_cycle(tcx.dep_context().sess(), error); - let value = handle_cycle_error(tcx, error); + let value = handle_cycle_error(*tcx.dep_context(), error, handler); cache.store_nocache(value) } +fn handle_cycle_error<CTX, V>( + tcx: CTX, + mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, + handler: HandleCycleError, +) -> V +where + CTX: DepContext, + V: Value<CTX>, +{ + use HandleCycleError::*; + match handler { + Error => { + error.emit(); + Value::from_cycle_error(tcx) + } + Fatal => { + error.emit(); + tcx.sess().abort_if_errors(); + unreachable!() + } + DelayBug => { + error.delay_as_bug(); + Value::from_cycle_error(tcx) + } + } +} + impl<'tcx, K> JobOwner<'tcx, K> where K: Eq + Hash + Clone, @@ -336,6 +365,7 @@ fn try_execute_query<CTX, C>( where C: QueryCache, C::Key: Clone + DepNodeParams<CTX::DepContext>, + C::Value: Value<CTX::DepContext>, CTX: QueryContext, { match JobOwner::<'_, C::Key>::try_start(&tcx, state, span, key.clone()) { @@ -686,6 +716,7 @@ pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> where Q: QueryDescription<CTX>, Q::Key: DepNodeParams<CTX::DepContext>, + Q::Value: Value<CTX::DepContext>, CTX: QueryContext, { let query = Q::make_vtable(tcx, &key); @@ -718,6 +749,7 @@ pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind where Q: QueryDescription<CTX>, Q::Key: DepNodeParams<CTX::DepContext>, + Q::Value: Value<CTX::DepContext>, CTX: QueryContext, { // We may be concurrently trying both execute and force a query. diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs new file mode 100644 index 00000000000..aeef66f86da --- /dev/null +++ b/compiler/rustc_query_system/src/values.rs @@ -0,0 +1,14 @@ +use crate::dep_graph::DepContext; + +pub trait Value<CTX: DepContext>: Sized { + fn from_cycle_error(tcx: CTX) -> Self; +} + +impl<CTX: DepContext, T> Value<CTX> for T { + default fn from_cycle_error(tcx: CTX) -> T { + tcx.sess().abort_if_errors(); + // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's + // non-trivial to define it earlier. + panic!("Value::from_cycle_error called without errors"); + } +} diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index c72981ed96f..101679aa6dc 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -525,6 +525,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match &item.kind { hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { @@ -839,6 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { use self::hir::TraitItemKind::*; match trait_item.kind { @@ -888,6 +890,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { use self::hir::ImplItemKind::*; match impl_item.kind { diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 5b95d73bd4d..9bc7fbfbe14 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -343,7 +343,7 @@ impl ParseSess { &'a self, err: impl SessionDiagnostic<'a>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(self) + err.into_diagnostic(&self.span_diagnostic) } pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { @@ -354,7 +354,7 @@ impl ParseSess { &'a self, warning: impl SessionDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self) + warning.into_diagnostic(&self.span_diagnostic) } pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { @@ -365,7 +365,7 @@ impl ParseSess { &'a self, fatal: impl SessionDiagnostic<'a, !>, ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(self) + fatal.into_diagnostic(&self.span_diagnostic) } pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a49af23be23..557edad548c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - EmissionGuarantee, ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan, + EmissionGuarantee, ErrorGuaranteed, FluentBundle, Handler, LazyFallbackBundle, MultiSpan, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -220,9 +220,9 @@ pub struct PerfStats { /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic]. #[rustc_diagnostic_item = "SessionDiagnostic"] pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { - /// Write out as a diagnostic out of `sess`. + /// Write out as a diagnostic out of `Handler`. #[must_use] - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, T>; + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>; } impl Session { diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index cb61f76af1d..b1de979e8f8 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{ self, Binder, Const, ExistentialPredicate, FloatTy, FnSig, IntTy, List, Region, RegionKind, - Term, Ty, TyCtxt, UintTy, + TermKind, Ty, TyCtxt, UintTy, }; use rustc_span::def_id::DefId; use rustc_span::symbol::sym; @@ -243,13 +243,9 @@ fn encode_predicate<'tcx>( let name = encode_ty_name(tcx, projection.item_def_id); let _ = write!(s, "u{}{}", name.len(), &name); s.push_str(&encode_substs(tcx, projection.substs, dict, options)); - match projection.term { - Term::Ty(ty) => { - s.push_str(&encode_ty(tcx, ty, dict, options)); - } - Term::Const(c) => { - s.push_str(&encode_const(tcx, c, dict, options)); - } + match projection.term.unpack() { + TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)), + TermKind::Const(c) => s.push_str(&encode_const(tcx, c, dict, options)), } } ty::ExistentialPredicate::AutoTrait(def_id) => { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 71fa5a44887..cfb8d47e545 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -543,9 +543,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { let name = cx.tcx.associated_item(projection.item_def_id).name; cx.push("p"); cx.push_ident(name.as_str()); - cx = match projection.term { - ty::Term::Ty(ty) => ty.print(cx), - ty::Term::Const(c) => c.print(cx), + cx = match projection.term.unpack() { + ty::TermKind::Ty(ty) => ty.print(cx), + ty::TermKind::Const(c) => c.print(cx), }?; } ty::ExistentialPredicate::AutoTrait(def_id) => { diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 92ce4d91d84..bcaf209f84b 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1130,7 +1130,7 @@ pub enum TagEncoding { /// Niche (values invalid for a type) encoding the discriminant: /// Discriminant and variant index coincide. - /// The variant `dataful_variant` contains a niche at an arbitrary + /// The variant `untagged_variant` contains a niche at an arbitrary /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to /// `(d - niche_variants.start).wrapping_add(niche_start)`. @@ -1139,7 +1139,7 @@ pub enum TagEncoding { /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). Niche { - dataful_variant: VariantIdx, + untagged_variant: VariantIdx, niche_variants: RangeInclusive<VariantIdx>, niche_start: u128, }, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 81977f25ca2..ab0afc54514 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ -use rustc_errors::{fluent, ErrorGuaranteed}; +use rustc_errors::{fluent, ErrorGuaranteed, Handler}; use rustc_macros::SessionDiagnostic; use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated}; -use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic}; +use rustc_session::{Limit, SessionDiagnostic}; use rustc_span::{Span, Symbol}; #[derive(SessionDiagnostic)] @@ -69,9 +69,9 @@ pub struct NegativePositiveConflict<'a> { impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> { fn into_diagnostic( self, - sess: &ParseSess, + handler: &Handler, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict); + let mut diag = handler.struct_err(fluent::trait_selection::negative_positive_conflict); diag.set_arg("trait_desc", self.trait_desc); diag.set_arg( "self_desc", diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1223c7ced7a..98e93ad3fc5 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -10,7 +10,7 @@ use crate::traits::project::ProjectAndUnifyResult; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{Region, RegionVid, Term}; +use rustc_middle::ty::{Region, RegionVid}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -612,7 +612,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { - if let Term::Ty(ty) = p.term().skip_binder() { + if let Some(ty) = p.term().skip_binder().ty() { matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty) } else { false diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 398635674ab..76c1ade0680 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -552,7 +552,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ) .ok() .flatten() - .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self))) + .unwrap_or_else(|| ty.super_fold_with(self).into()) }; // For cases like #95134 we would like to catch overflows early // otherwise they slip away away and cause ICE. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index bb6009cb22a..9a571837e9f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -129,9 +129,9 @@ pub fn predicate_obligations<'a, 'tcx>( } ty::PredicateKind::Projection(t) => { wf.compute_projection(t.projection_ty); - wf.compute(match t.term { - ty::Term::Ty(ty) => ty.into(), - ty::Term::Const(c) => c.into(), + wf.compute(match t.term.unpack() { + ty::TermKind::Ty(ty) => ty.into(), + ty::TermKind::Const(c) => c.into(), }) } ty::PredicateKind::WellFormed(arg) => { @@ -434,6 +434,7 @@ impl<'tcx> WfPredicates<'tcx> { } /// Pushes all the predicates needed to validate that `ty` is WF into `out`. + #[instrument(level = "debug", skip(self))] fn compute(&mut self, arg: GenericArg<'tcx>) { let mut walker = arg.walk(); let param_env = self.param_env; @@ -488,6 +489,8 @@ impl<'tcx> WfPredicates<'tcx> { } }; + debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind()); + match *ty.kind() { ty::Bool | ty::Char diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index ff39bf36129..a9152bdc597 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -29,6 +29,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.tcx().sess.emit_err(MissingTypeParams { span, def_span: self.tcx().def_span(def_id), + span_snippet: self.tcx().sess.source_map().span_to_snippet(span).ok(), missing_type_params, empty_generic_args, }); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 14f04ddc868..801063583e6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1183,11 +1183,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // `<T as Iterator>::Item = u32` let assoc_item_def_id = projection_ty.skip_binder().item_def_id; let def_kind = tcx.def_kind(assoc_item_def_id); - match (def_kind, term) { - (hir::def::DefKind::AssocTy, ty::Term::Ty(_)) - | (hir::def::DefKind::AssocConst, ty::Term::Const(_)) => (), + match (def_kind, term.unpack()) { + (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_)) + | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (), (_, _) => { - let got = if let ty::Term::Ty(_) = term { "type" } else { "constant" }; + let got = if let Some(_) = term.ty() { "type" } else { "constant" }; let expected = def_kind.descr(assoc_item_def_id); tcx.sess .struct_span_err( @@ -1375,9 +1375,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let pred = bound_predicate.rebind(pred); // A `Self` within the original bound will be substituted with a // `trait_object_dummy_self`, so check for that. - let references_self = match pred.skip_binder().term { - ty::Term::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - ty::Term::Const(c) => c.ty().walk().any(|arg| arg == dummy_self.into()), + let references_self = match pred.skip_binder().term.unpack() { + ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), + ty::TermKind::Const(c) => { + c.ty().walk().any(|arg| arg == dummy_self.into()) + } }; // If the projection output contains `Self`, force the user to @@ -2695,6 +2697,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { result_ty } + #[instrument(level = "debug", skip(self), ret)] fn impl_trait_ty_to_ty( &self, def_id: DefId, @@ -2743,9 +2746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); debug!("impl_trait_ty_to_ty: substs={:?}", substs); - let ty = tcx.mk_opaque(def_id, substs); - debug!("impl_trait_ty_to_ty: {}", ty); - ty + tcx.mk_opaque(def_id, substs) } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> { diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index a9071cd1fd9..c597efbe746 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{ - self, AssocKind, DefIdTree, GenericParamDefKind, ProjectionPredicate, ProjectionTy, Term, + self, AssocKind, DefIdTree, GenericParamDefKind, ProjectionPredicate, ProjectionTy, ToPredicate, Ty, TypeVisitable, }; use rustc_span::symbol::Ident; @@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_output_ty.zip(opt_output_assoc_item).map(|(output_ty, output_assoc_item)| { ty::Binder::dummy(ty::PredicateKind::Projection(ProjectionPredicate { projection_ty: ProjectionTy { substs, item_def_id: output_assoc_item.def_id }, - term: Term::Ty(output_ty), + term: output_ty.into(), })) .to_predicate(self.tcx) }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 6236ad370df..e70f728d7dc 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -573,6 +573,7 @@ fn get_new_lifetime_name<'tcx>( /// Returns the predicates defined on `item_def_id` of the form /// `X: Foo` where `X` is the type parameter `def_id`. +#[instrument(level = "trace", skip(tcx))] fn type_param_predicates( tcx: TyCtxt<'_>, (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), @@ -679,7 +680,7 @@ impl<'tcx> ItemCtxt<'tcx> { assoc_name: Option<Ident>, ) -> Vec<(ty::Predicate<'tcx>, Span)> { let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); - debug!(?param_def_id); + trace!(?param_def_id); ast_generics .predicates .iter() @@ -708,9 +709,8 @@ impl<'tcx> ItemCtxt<'tcx> { .collect() } + #[instrument(level = "trace", skip(self))] fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { - debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name); - match b { hir::GenericBound::Trait(poly_trait_ref, _) => { let trait_ref = &poly_trait_ref.trait_ref; @@ -2105,11 +2105,10 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. +#[instrument(level = "trace", skip(tcx), ret)] fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; - debug!("explicit_predicates_of(def_id={:?})", def_id); - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let node = tcx.hir().get(hir_id); @@ -2224,6 +2223,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP + has_own_self as u32 + early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32; + trace!(?predicates); + trace!(?ast_generics); + // Collect the predicates that were written inline by the user on each // type parameter (e.g., `<T: Foo>`). for param in ast_generics.params { @@ -2244,7 +2246,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Some((param.hir_id, ast_generics.predicates)), param.span, ); + trace!(?bounds); predicates.extend(bounds.predicates(tcx, param_ty)); + trace!(?predicates); } GenericParamKind::Const { .. } => { // Bounds on const parameters are currently not possible. @@ -2253,6 +2257,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } + trace!(?predicates); // Add in the bounds that appear in the where-clause. for predicate in ast_generics.predicates { match predicate { @@ -2338,12 +2343,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP ); } - let result = ty::GenericPredicates { + ty::GenericPredicates { parent: generics.parent, predicates: tcx.arena.alloc_from_iter(predicates), - }; - debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result); - result + } } fn const_evaluatable_predicates_of<'tcx>( diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 0d2b75d3328..318e8f581f7 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -53,6 +53,7 @@ fn associated_type_bounds<'tcx>( /// impl trait it isn't possible to write a suitable predicate on the /// containing function and for type-alias impl trait we don't have a backwards /// compatibility issue. +#[instrument(level = "trace", skip(tcx), ret)] fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: DefId, @@ -67,6 +68,8 @@ fn opaque_type_bounds<'tcx>( let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + debug!(?bounds); + tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) }) } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 14c0558cdde..0d2e6674585 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -1,8 +1,8 @@ //! Errors emitted by typeck. -use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler}; use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_middle::ty::Ty; -use rustc_session::{parse::ParseSess, SessionDiagnostic}; +use rustc_session::SessionDiagnostic; use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(SessionDiagnostic)] @@ -244,14 +244,15 @@ pub struct UnconstrainedOpaqueType { pub struct MissingTypeParams { pub span: Span, pub def_span: Span, + pub span_snippet: Option<String>, pub missing_type_params: Vec<Symbol>, pub empty_generic_args: bool, } // Manual implementation of `SessionDiagnostic` to be able to call `span_to_snippet`. impl<'a> SessionDiagnostic<'a> for MissingTypeParams { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = sess.span_diagnostic.struct_span_err_with_code( + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut err = handler.struct_span_err_with_code( self.span, rustc_errors::fluent::typeck::missing_type_params, error_code!(E0393), @@ -269,12 +270,9 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams { err.span_label(self.def_span, rustc_errors::fluent::typeck::label); let mut suggested = false; - if let (Ok(snippet), true) = ( - sess.source_map().span_to_snippet(self.span), - // Don't suggest setting the type params if there are some already: the order is - // tricky to get right and the user will already know what the syntax is. - self.empty_generic_args, - ) { + // Don't suggest setting the type params if there are some already: the order is + // tricky to get right and the user will already know what the syntax is. + if let Some(snippet) = self.span_snippet && self.empty_generic_args { if snippet.ends_with('>') { // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion // we would have to preserve the right order. For now, as clearly the user is diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index d79450e1ae7..4fe213ffeea 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -271,11 +271,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } for projection in data.projection_bounds() { - match projection.skip_binder().term { - ty::Term::Ty(ty) => { + match projection.skip_binder().term.unpack() { + ty::TermKind::Ty(ty) => { self.add_constraints_from_ty(current, ty, self.invariant); } - ty::Term::Const(c) => { + ty::TermKind::Const(c) => { self.add_constraints_from_const(current, c, self.invariant) } } diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 91cff3217d2..2dc12a18a8a 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -992,6 +992,9 @@ pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> { /// the global stream. /// /// However, if the actual I/O causes an error, this function does panic. +/// +/// Writing to non-blocking stdout/stderr can cause an error, which will lead +/// this function to panic. fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str) where T: Write, diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index a5003c66fca..6e4ba1404e5 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -49,6 +49,9 @@ macro_rules! panic { /// /// Panics if writing to `io::stdout()` fails. /// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// /// # Examples /// /// ``` @@ -107,6 +110,9 @@ macro_rules! print { /// /// Panics if writing to [`io::stdout`] fails. /// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// /// [`io::stdout`]: crate::io::stdout /// /// # Examples @@ -147,6 +153,9 @@ macro_rules! println { /// /// Panics if writing to `io::stderr` fails. /// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// /// # Examples /// /// ``` @@ -179,6 +188,9 @@ macro_rules! eprint { /// /// Panics if writing to `io::stderr` fails. /// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// /// # Examples /// /// ``` diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 78d6ce3eff4..89d0ab59be8 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -66,6 +66,7 @@ pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; pub type LPWSABUF = *mut WSABUF; pub type LPWSAOVERLAPPED = *mut c_void; pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void; +pub type BCRYPT_ALG_HANDLE = LPVOID; pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; pub type PLARGE_INTEGER = *mut c_longlong; @@ -278,6 +279,7 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; +pub const STATUS_NOT_SUPPORTED: NTSTATUS = 0xC00000BB_u32 as _; // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values @@ -285,7 +287,8 @@ pub fn nt_success(status: NTSTATUS) -> bool { status >= 0 } -pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81; +// "RNG\0" +pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0]; #[repr(C)] pub struct UNICODE_STRING { @@ -1229,11 +1232,18 @@ extern "system" { // >= Vista / Server 2008 // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom pub fn BCryptGenRandom( - hAlgorithm: LPVOID, + hAlgorithm: BCRYPT_ALG_HANDLE, pBuffer: *mut u8, cbBuffer: ULONG, dwFlags: ULONG, ) -> NTSTATUS; + pub fn BCryptOpenAlgorithmProvider( + phalgorithm: *mut BCRYPT_ALG_HANDLE, + pszAlgId: LPCWSTR, + pszimplementation: LPCWSTR, + dwflags: ULONG, + ) -> NTSTATUS; + pub fn BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE, dwFlags: ULONG) -> NTSTATUS; } // Functions that aren't available on every version of Windows that we support, diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index c2ad592dfea..155d0297e49 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -403,7 +403,7 @@ impl File { mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(), ))?; if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { - reparse_tag = attr_tag.ReparseTag; + attr.reparse_tag = attr_tag.ReparseTag; } } Ok(attr) diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index 8b969788436..d6cd8f80271 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -22,7 +22,6 @@ //! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom //! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom //! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles -use crate::io; use crate::mem; use crate::ptr; use crate::sys::c; @@ -34,35 +33,94 @@ use crate::sys::c; /// [`HashMap`]: crate::collections::HashMap /// [`RandomState`]: crate::collections::hash_map::RandomState pub fn hashmap_random_keys() -> (u64, u64) { - let mut v = (0, 0); - let ret = unsafe { - let size = mem::size_of_val(&v).try_into().unwrap(); - c::BCryptGenRandom( - // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+. - // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails. - ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE), - ptr::addr_of_mut!(v).cast(), - size, - 0, - ) - }; - if ret != 0 { fallback_rng() } else { v } + Rng::open().and_then(|rng| rng.gen_random_keys()).unwrap_or_else(fallback_rng) +} + +struct Rng(c::BCRYPT_ALG_HANDLE); +impl Rng { + #[cfg(miri)] + fn open() -> Result<Self, c::NTSTATUS> { + const BCRYPT_RNG_ALG_HANDLE: c::BCRYPT_ALG_HANDLE = ptr::invalid_mut(0x81); + let _ = ( + c::BCryptOpenAlgorithmProvider, + c::BCryptCloseAlgorithmProvider, + c::BCRYPT_RNG_ALGORITHM, + c::STATUS_NOT_SUPPORTED, + ); + Ok(Self(BCRYPT_RNG_ALG_HANDLE)) + } + #[cfg(not(miri))] + // Open a handle to the RNG algorithm. + fn open() -> Result<Self, c::NTSTATUS> { + use crate::sync::atomic::AtomicPtr; + use crate::sync::atomic::Ordering::{Acquire, Release}; + const ERROR_VALUE: c::LPVOID = ptr::invalid_mut(usize::MAX); + + // An atomic is used so we don't need to reopen the handle every time. + static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut()); + + let mut handle = HANDLE.load(Acquire); + // We use a sentinel value to designate an error occurred last time. + if handle == ERROR_VALUE { + Err(c::STATUS_NOT_SUPPORTED) + } else if handle.is_null() { + let status = unsafe { + c::BCryptOpenAlgorithmProvider( + &mut handle, + c::BCRYPT_RNG_ALGORITHM.as_ptr(), + ptr::null(), + 0, + ) + }; + if c::nt_success(status) { + // If another thread opens a handle first then use that handle instead. + let result = HANDLE.compare_exchange(ptr::null_mut(), handle, Release, Acquire); + if let Err(previous_handle) = result { + // Close our handle and return the previous one. + unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) }; + handle = previous_handle; + } + Ok(Self(handle)) + } else { + HANDLE.store(ERROR_VALUE, Release); + Err(status) + } + } else { + Ok(Self(handle)) + } + } + + fn gen_random_keys(self) -> Result<(u64, u64), c::NTSTATUS> { + let mut v = (0, 0); + let status = unsafe { + let size = mem::size_of_val(&v).try_into().unwrap(); + c::BCryptGenRandom(self.0, ptr::addr_of_mut!(v).cast(), size, 0) + }; + if c::nt_success(status) { Ok(v) } else { Err(status) } + } } /// Generate random numbers using the fallback RNG function (RtlGenRandom) #[cfg(not(target_vendor = "uwp"))] #[inline(never)] -fn fallback_rng() -> (u64, u64) { +fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { let mut v = (0, 0); let ret = unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; - if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) } + if ret != 0 { + v + } else { + panic!( + "RNG broken: {rng_status:#x}, fallback RNG broken: {}", + crate::io::Error::last_os_error() + ) + } } /// We can't use RtlGenRandom with UWP, so there is no fallback #[cfg(target_vendor = "uwp")] #[inline(never)] -fn fallback_rng() -> (u64, u64) { - panic!("fallback RNG broken: RtlGenRandom() not supported on UWP"); +fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { + panic!("RNG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP"); } diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 3c9eecbe128..1d5ad3cce18 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -422,6 +422,7 @@ Next, we'll build a package manifest as defined by our manifest: ```sh ${SDK_PATH}/tools/${ARCH}/pm \ + -api-level $(${SDK_PATH}/tools/${ARCH}/ffx version -v | grep "api-level" | head -1 | awk -F ' ' '{print $2}') \ -o pkg/hello_fuchsia_manifest \ -m pkg/hello_fuchsia.manifest \ build \ diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index 025f320e3a1..991c881bae1 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -132,9 +132,11 @@ while work_list: work_list |= set(item["inner"]["items"]) - visited elif item["kind"] == "struct": check_generics(item["inner"]["generics"]) - work_list |= ( - set(item["inner"]["fields"]) | set(item["inner"]["impls"]) - ) - visited + work_list |= set(item["inner"]["impls"]) - visited + if "tuple" in item["inner"]["kind"]: + work_list |= set(filter(None, item["inner"]["kind"]["tuple"])) - visited + elif "plain" in item["inner"]["kind"]: + work_list |= set(item["inner"]["kind"]["plain"]["fields"]) - visited elif item["kind"] == "struct_field": check_type(item["inner"]) elif item["kind"] == "enum": @@ -144,10 +146,10 @@ while work_list: ) - visited elif item["kind"] == "variant": if item["inner"]["variant_kind"] == "tuple": - for ty in item["inner"]["variant_inner"]: - check_type(ty) + for field_id in filter(None, item["inner"]["variant_inner"]): + work_list.add(field_id) elif item["inner"]["variant_kind"] == "struct": - work_list |= set(item["inner"]["variant_inner"]) - visited + work_list |= set(item["inner"]["variant_inner"]["fields"]) - visited elif item["kind"] in ("function", "method"): check_generics(item["inner"]["generics"]) check_decl(item["inner"]["decl"]) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index be2227f47af..980a1485b59 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -370,9 +370,9 @@ fn clean_type_outlives_predicate<'tcx>( } fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term { - match term { - ty::Term::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)), - ty::Term::Const(c) => Term::Constant(clean_middle_const(c, cx)), + match term.unpack() { + ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)), + ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)), } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d6bb7c6c4fc..2077cf71b2e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2532,7 +2532,8 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 64); + #[cfg(not(bootstrap))] + static_assert_size!(GenericArg, 56); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 3502d97d470..7665417cb5c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -609,11 +609,6 @@ h2.location a { text-align: center; } -#results > table { - width: 100%; - table-layout: fixed; -} - .content > .example-wrap pre.line-numbers { position: relative; -webkit-user-select: none; @@ -704,9 +699,6 @@ pre, .rustdoc.source .example-wrap { #main-content { position: relative; } -#main-content > .since { - top: inherit; -} .content table { border-spacing: 0 5px; @@ -752,11 +744,6 @@ pre, .rustdoc.source .example-wrap { font-size: 0.875rem; } -.content .methods > div:not(.notable-traits):not(.method) { - margin-left: 40px; - margin-bottom: 15px; -} - .item-info { display: block; } @@ -770,10 +757,6 @@ pre, .rustdoc.source .example-wrap { margin-left: 24px; } -.sub-variant > div > .item-info { - margin-top: initial; -} - .content .impl-items .docblock, .content .impl-items .item-info { margin-bottom: .6em; } @@ -1760,7 +1743,6 @@ in storage.js plus the media query with (min-width: 701px) padding-top: 0px; } - .rustdoc, .main-heading { flex-direction: column; } @@ -2047,11 +2029,6 @@ in storage.js plus the media query with (min-width: 701px) height: 73px; } - #main-content > table td { - word-break: break-word; - width: 50%; - } - #crate-search { border-radius: 4px; } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4d009316730..1177d482ac0 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -304,11 +304,19 @@ impl FromWithTcx<clean::Struct> for Struct { fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { let fields_stripped = struct_.has_stripped_entries(); let clean::Struct { struct_type, generics, fields } = struct_; + + let kind = match struct_type { + CtorKind::Fn => StructKind::Tuple(ids_keeping_stripped(fields, tcx)), + CtorKind::Const => { + assert!(fields.is_empty()); + StructKind::Unit + } + CtorKind::Fictive => StructKind::Plain { fields: ids(fields, tcx), fields_stripped }, + }; + Struct { - struct_type: from_ctor_kind(struct_type), + kind, generics: generics.into_tcx(tcx), - fields_stripped, - fields: ids(fields, tcx), impls: Vec::new(), // Added in JsonRenderer::item } } @@ -327,14 +335,6 @@ impl FromWithTcx<clean::Union> for Union { } } -pub(crate) fn from_ctor_kind(struct_type: CtorKind) -> StructType { - match struct_type { - CtorKind::Fictive => StructType::Plain, - CtorKind::Fn => StructType::Tuple, - CtorKind::Const => StructType::Unit, - } -} - pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header { Header { async_: header.is_async(), @@ -644,36 +644,16 @@ impl FromWithTcx<clean::Enum> for Enum { } } -impl FromWithTcx<clean::VariantStruct> for Struct { - fn from_tcx(struct_: clean::VariantStruct, tcx: TyCtxt<'_>) -> Self { - let fields_stripped = struct_.has_stripped_entries(); - let clean::VariantStruct { struct_type, fields } = struct_; - Struct { - struct_type: from_ctor_kind(struct_type), - generics: Generics { params: vec![], where_predicates: vec![] }, - fields_stripped, - fields: ids(fields, tcx), - impls: Vec::new(), - } - } -} - impl FromWithTcx<clean::Variant> for Variant { fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { use clean::Variant::*; match variant { CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))), - Tuple(fields) => Variant::Tuple( - fields - .into_iter() - .filter_map(|f| match *f.kind { - clean::StructFieldItem(ty) => Some(ty.into_tcx(tcx)), - clean::StrippedItem(_) => None, - _ => unreachable!(), - }) - .collect(), - ), - Struct(s) => Variant::Struct(ids(s.fields, tcx)), + Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)), + Struct(s) => Variant::Struct { + fields_stripped: s.has_stripped_entries(), + fields: ids(s.fields, tcx), + }, } } } @@ -796,3 +776,19 @@ fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id> .map(|i| from_item_id_with_name(i.item_id, tcx, i.name)) .collect() } + +fn ids_keeping_stripped( + items: impl IntoIterator<Item = clean::Item>, + tcx: TyCtxt<'_>, +) -> Vec<Option<Id>> { + items + .into_iter() + .map(|i| { + if !i.is_stripped() && !i.is_keyword() { + Some(from_item_id_with_name(i.item_id, tcx, i.name)) + } else { + None + } + }) + .collect() +} diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index d25f68b3743..13bafa506e4 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 19; +pub const FORMAT_VERSION: u32 = 21; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -289,14 +289,40 @@ pub struct Union { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Struct { - pub struct_type: StructType, + pub kind: StructKind, pub generics: Generics, - pub fields_stripped: bool, - pub fields: Vec<Id>, pub impls: Vec<Id>, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum StructKind { + /// A struct with no fields and no parentheses. + /// + /// ```rust + /// pub struct Unit; + /// ``` + Unit, + /// A struct with unnamed fields. + /// + /// ```rust + /// pub struct TupleStruct(i32); + /// pub struct EmptyTupleStruct(); + /// ``` + /// + /// All [`Id`]'s will point to [`ItemEnum::StructField`]. Private and + /// `#[doc(hidden)]` fields will be given as `None` + Tuple(Vec<Option<Id>>), + /// A struct with nammed fields. + /// + /// ```rust + /// pub struct PlainStruct { x: i32 } + /// pub struct EmptyPlainStruct {} + /// ``` + Plain { fields: Vec<Id>, fields_stripped: bool }, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Enum { pub generics: Generics, pub variants_stripped: bool, @@ -308,9 +334,36 @@ pub struct Enum { #[serde(rename_all = "snake_case")] #[serde(tag = "variant_kind", content = "variant_inner")] pub enum Variant { + /// A variant with no parentheses, and possible discriminant. + /// + /// ```rust + /// enum Demo { + /// PlainVariant, + /// PlainWithDiscriminant = 1, + /// } + /// ``` Plain(Option<Discriminant>), - Tuple(Vec<Type>), - Struct(Vec<Id>), + /// A variant with unnamed fields. + /// + /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None` + /// instead of being ommited, because order matters. + /// + /// ```rust + /// enum Demo { + /// TupleVariant(i32), + /// EmptyTupleVariant(), + /// } + /// ``` + Tuple(Vec<Option<Id>>), + /// A variant with named fields. + /// + /// ```rust + /// enum Demo { + /// StructVariant { x: i32 }, + /// EmptyStructVariant {}, + /// } + /// ``` + Struct { fields: Vec<Id>, fields_stripped: bool }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -331,14 +384,6 @@ pub struct Discriminant { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum StructType { - Plain, - Tuple, - Unit, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Header { #[serde(rename = "const")] pub const_: bool, diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs index e7f6447ed87..399ff54b294 100644 --- a/src/rustdoc-json-types/tests.rs +++ b/src/rustdoc-json-types/tests.rs @@ -3,10 +3,8 @@ use super::*; #[test] fn test_struct_info_roundtrip() { let s = ItemEnum::Struct(Struct { - struct_type: StructType::Plain, generics: Generics { params: vec![], where_predicates: vec![] }, - fields_stripped: false, - fields: vec![], + kind: StructKind::Plain { fields: vec![], fields_stripped: false }, impls: vec![], }); diff --git a/src/test/codegen/issue-98294-get-mut-copy-from-slice-opt.rs b/src/test/codegen/issue-98294-get-mut-copy-from-slice-opt.rs new file mode 100644 index 00000000000..7da29cd7952 --- /dev/null +++ b/src/test/codegen/issue-98294-get-mut-copy-from-slice-opt.rs @@ -0,0 +1,19 @@ +// min-llvm-version: 15.0.0 +// ignore-debug: The debug assertions get in the way +// compile-flags: -O + +#![crate_type = "lib"] + +// There should be no calls to panic / len_mismatch_fail. + +#[no_mangle] +pub fn test(a: &mut [u8], offset: usize, bytes: &[u8]) { + // CHECK-LABEL: @test( + // CHECK-NOT: call + // CHECK: call void @llvm.memcpy + // CHECK-NOT: call + // CHECK: } + if let Some(dst) = a.get_mut(offset..offset + bytes.len()) { + dst.copy_from_slice(bytes); + } +} diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 45d5ddf5c0e..7f1be6f2784 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -53,8 +53,8 @@ // cdb-command: dx niche128_none // cdb-check: niche128_none : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >] -// cdb-command: dx wrapping_niche128_dataful -// cdb-check: wrapping_niche128_dataful : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] +// cdb-command: dx wrapping_niche128_untagged +// cdb-check: wrapping_niche128_untagged : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>] // cdb-check: [+0x[...]] __0 [Type: msvc_pretty_enums::Wrapping128] // cdb-command: dx wrapping_niche128_none1 @@ -213,7 +213,7 @@ fn main() { let niche128_some = Some(NonZeroI128::new(123456).unwrap()); let niche128_none: Option<NonZeroI128> = None; - let wrapping_niche128_dataful = + let wrapping_niche128_untagged = unsafe { Wrapping128Niche::X(Wrapping128(340282366920938463463374607431768211454)) }; let wrapping_niche128_none1 = Wrapping128Niche::Y; let wrapping_niche128_none2 = Wrapping128Niche::Z; diff --git a/src/test/incremental/issue-100521-change-struct-name-assocty.rs b/src/test/incremental/issue-100521-change-struct-name-assocty.rs new file mode 100644 index 00000000000..7f8d1e60881 --- /dev/null +++ b/src/test/incremental/issue-100521-change-struct-name-assocty.rs @@ -0,0 +1,65 @@ +// revisions: rpass1 rpass2 + +pub fn foo() { + bar(); + baz::<()>(); +} + +fn bar() +where + <() as Table>::AllColumns:, +{ +} + +fn baz<W>() +where + W: AsQuery, + <W as AsQuery>::Query:, +{ +} + +trait AsQuery { + type Query; +} + +trait UnimplementedTrait {} + +impl<T> AsQuery for T +where + T: UnimplementedTrait, +{ + type Query = (); +} + +struct Wrapper<Expr>(Expr); + +impl<Ret> AsQuery for Wrapper<Ret> { + type Query = (); +} + +impl AsQuery for () +where + Wrapper<<() as Table>::AllColumns>: AsQuery, +{ + type Query = (); +} + +trait Table { + type AllColumns; +} + +#[cfg(rpass1)] +impl Table for () { + type AllColumns = Checksum1; +} +#[cfg(rpass1)] +struct Checksum1; + +#[cfg(rpass2)] +impl Table for () { + type AllColumns = Checksum2; +} +#[cfg(rpass2)] +struct Checksum2; + +fn main() {} diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 0e4c486e464..e7bde81d4ca 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -7,7 +7,7 @@ unsafe fn foo(z: *mut usize) -> u32 { 99 } -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir fn main() { let mut x = [42, 43, 44]; diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir deleted file mode 100644 index 27f883ed321..00000000000 --- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir +++ /dev/null @@ -1,64 +0,0 @@ -// MIR for `main` after SimplifyCfg-elaborate-drops - -fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/array-index-is-temporary.rs:+0:11: +0:11 - let mut _1: [u32; 3]; // in scope 0 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - let mut _4: &mut usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - let mut _5: u32; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:12: +4:29 - let mut _6: *mut usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - let _7: usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - let mut _8: usize; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - let mut _9: bool; // in scope 0 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - scope 1 { - debug x => _1; // in scope 1 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - let mut _2: usize; // in scope 1 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 - scope 2 { - debug y => _2; // in scope 2 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 - let _3: *mut usize; // in scope 2 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 - scope 3 { - debug z => _3; // in scope 3 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 - scope 4 { - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/array-index-is-temporary.rs:+1:9: +1:14 - _1 = [const 42_u32, const 43_u32, const 44_u32]; // scope 0 at $DIR/array-index-is-temporary.rs:+1:17: +1:29 - StorageLive(_2); // scope 1 at $DIR/array-index-is-temporary.rs:+2:9: +2:14 - _2 = const 1_usize; // scope 1 at $DIR/array-index-is-temporary.rs:+2:17: +2:18 - StorageLive(_3); // scope 2 at $DIR/array-index-is-temporary.rs:+3:9: +3:10 - StorageLive(_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - _4 = &mut _2; // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - _3 = &raw mut (*_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:25: +3:31 - StorageDead(_4); // scope 2 at $DIR/array-index-is-temporary.rs:+3:31: +3:32 - StorageLive(_5); // scope 3 at $DIR/array-index-is-temporary.rs:+4:12: +4:29 - StorageLive(_6); // scope 4 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - _6 = _3; // scope 4 at $DIR/array-index-is-temporary.rs:+4:25: +4:26 - _5 = foo(move _6) -> bb1; // scope 4 at $DIR/array-index-is-temporary.rs:+4:21: +4:27 - // mir::Constant - // + span: $DIR/array-index-is-temporary.rs:16:21: 16:24 - // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(<ZST>) } - } - - bb1: { - StorageDead(_6); // scope 4 at $DIR/array-index-is-temporary.rs:+4:26: +4:27 - StorageLive(_7); // scope 3 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - _7 = _2; // scope 3 at $DIR/array-index-is-temporary.rs:+4:7: +4:8 - _8 = Len(_1); // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - _9 = Lt(_7, _8); // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:9 - } - - bb2: { - _1[_7] = move _5; // scope 3 at $DIR/array-index-is-temporary.rs:+4:5: +4:29 - StorageDead(_5); // scope 3 at $DIR/array-index-is-temporary.rs:+4:28: +4:29 - StorageDead(_7); // scope 3 at $DIR/array-index-is-temporary.rs:+4:29: +4:30 - _0 = const (); // scope 0 at $DIR/array-index-is-temporary.rs:+0:11: +5:2 - StorageDead(_3); // scope 2 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - StorageDead(_2); // scope 1 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/array-index-is-temporary.rs:+5:1: +5:2 - return; // scope 0 at $DIR/array-index-is-temporary.rs:+5:2: +5:2 - } -} diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir index 27f883ed321..27f883ed321 100644 --- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir +++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs index 049a97816f6..232bcc7b27d 100644 --- a/src/test/mir-opt/inline/inline-into-box-place.rs +++ b/src/test/mir-opt/inline/inline-into-box-place.rs @@ -1,7 +1,7 @@ // ignore-endian-big // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -Z mir-opt-level=4 -// EMIT_MIR_FOR_EACH_BIT_WIDTH + #![feature(box_syntax)] // EMIT_MIR inline_into_box_place.main.Inline.diff fn main() { diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff deleted file mode 100644 index 7017413ad38..00000000000 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ /dev/null @@ -1,82 +0,0 @@ -- // MIR for `main` before Inline -+ // MIR for `main` after Inline - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:+0:11: +0:11 - let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:9: +1:11 - let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 - let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 -+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 - scope 1 { - debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11 - } - scope 2 { - } -+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:+1:9: +1:11 - _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:29: 8:43 - // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) } - } - - bb1: { - StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - _7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ _9 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - // mir::Constant -- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 -- // + user_ty: UserType(1) -- // + literal: Const { ty: fn() -> Vec<u32> {Vec::<u32>::new}, val: Value(<ZST>) } -- } -- -- bb2: { -+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ // + user_ty: UserType(0) -+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) } -+ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 - _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 - _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:+0:11: +2:2 -- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 -+ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 - } - -- bb3: { -+ bb2: { - StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:+2:1: +2:2 - return; // scope 0 at $DIR/inline-into-box-place.rs:+2:2: +2:2 - } - -- bb4 (cleanup): { -+ bb3 (cleanup): { - resume; // scope 0 at $DIR/inline-into-box-place.rs:+0:1: +2:2 -- } -- -- bb5 (cleanup): { -- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 -- // mir::Constant -- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 -- // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(<ZST>) } - } - } - diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff index 7017413ad38..7017413ad38 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue-41697.rs index 5c34d8e68d0..cbd8633a345 100644 --- a/src/test/mir-opt/issue-41697.rs +++ b/src/test/mir-opt/issue-41697.rs @@ -13,7 +13,7 @@ trait Foo { fn get(&self) -> [u8; 2]; } -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir impl Foo for [u8; 1+1] { fn get(&self) -> [u8; 2] { diff --git a/src/test/mir-opt/issue-72181.rs b/src/test/mir-opt/issue-72181.rs index 844d53a4b2b..ebb5f5042fc 100644 --- a/src/test/mir-opt/issue-72181.rs +++ b/src/test/mir-opt/issue-72181.rs @@ -11,14 +11,14 @@ union Foo { b: Never } -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR issue_72181.foo.mir_map.0.mir fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 } // EMIT_MIR issue_72181.bar.mir_map.0.mir fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x } -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR issue_72181.main.mir_map.0.mir fn main() { let _ = mem::size_of::<Foo>(); diff --git a/src/test/mir-opt/issue-73223.rs b/src/test/mir-opt/issue-73223.rs index 9e731c40908..be114cab719 100644 --- a/src/test/mir-opt/issue-73223.rs +++ b/src/test/mir-opt/issue-73223.rs @@ -8,5 +8,5 @@ fn main() { assert_eq!(split, 1); } -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff diff --git a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir deleted file mode 100644 index 047b24db466..00000000000 --- a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir +++ /dev/null @@ -1,20 +0,0 @@ -// MIR for `<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}` after SimplifyCfg-promote-consts - -<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}: usize = { - let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - let mut _1: (usize, bool); // in scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - - bb0: { - _1 = CheckedAdd(const 1_usize, const 1_usize); // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - } - - bb1: { - _0 = move (_1.0: usize); // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - return; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - } - - bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-41697.rs:+0:19: +0:22 - } -} diff --git a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir index 047b24db466..047b24db466 100644 --- a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir +++ b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir diff --git a/src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir deleted file mode 100644 index 972ce1d5078..00000000000 --- a/src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir +++ /dev/null @@ -1,17 +0,0 @@ -// MIR for `bar` 0 mir_map - -fn bar(_1: [(Never, u32); 1]) -> u32 { - let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:+0:40: +0:43 - let _2: u32; // in scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 - scope 1 { - debug x => _2; // in scope 1 at $DIR/issue-72181.rs:+0:13: +0:14 - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 - _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue-72181.rs:+0:13: +0:14 - _0 = _2; // scope 1 at $DIR/issue-72181.rs:+0:46: +0:47 - StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:+0:48: +0:49 - return; // scope 0 at $DIR/issue-72181.rs:+0:49: +0:49 - } -} diff --git a/src/test/mir-opt/issue_72181.bar.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir index 972ce1d5078..972ce1d5078 100644 --- a/src/test/mir-opt/issue_72181.bar.mir_map.0.32bit.mir +++ b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir deleted file mode 100644 index 534f131ea93..00000000000 --- a/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir +++ /dev/null @@ -1,27 +0,0 @@ -// MIR for `foo` 0 mir_map - -fn foo(_1: [(Never, u32); 1]) -> u32 { - debug xs => _1; // in scope 0 at $DIR/issue-72181.rs:+0:8: +0:10 - let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:+0:34: +0:37 - let _2: usize; // in scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - let mut _3: usize; // in scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - let mut _4: bool; // in scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - _2 = const 0_usize; // scope 0 at $DIR/issue-72181.rs:+0:43: +0:44 - _3 = Len(_1); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - _4 = Lt(_2, _3); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-72181.rs:+0:40: +0:45 - } - - bb1: { - _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue-72181.rs:+0:40: +0:47 - StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:+0:48: +0:49 - return; // scope 0 at $DIR/issue-72181.rs:+0:49: +0:49 - } - - bb2 (cleanup): { - resume; // scope 0 at $DIR/issue-72181.rs:+0:1: +0:49 - } -} diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir index 534f131ea93..534f131ea93 100644 --- a/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir +++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir deleted file mode 100644 index 425906f84fc..00000000000 --- a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir +++ /dev/null @@ -1,62 +0,0 @@ -// MIR for `main` 0 mir_map - -fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-72181.rs:+0:11: +0:11 - let mut _1: usize; // in scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 - let mut _3: Foo; // in scope 0 at $DIR/issue-72181.rs:+3:14: +3:27 - let mut _4: Foo; // in scope 0 at $DIR/issue-72181.rs:+3:29: +3:42 - let mut _5: u64; // in scope 0 at $DIR/issue-72181.rs:+4:13: +4:30 - let _6: usize; // in scope 0 at $DIR/issue-72181.rs:+4:24: +4:25 - let mut _7: usize; // in scope 0 at $DIR/issue-72181.rs:+4:22: +4:26 - let mut _8: bool; // in scope 0 at $DIR/issue-72181.rs:+4:22: +4:26 - scope 1 { - let _2: [Foo; 2]; // in scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 - scope 2 { - debug f => _2; // in scope 2 at $DIR/issue-72181.rs:+3:9: +3:10 - scope 3 { - } - scope 4 { - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 - _1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-72181.rs:+1:13: +1:34 - // mir::Constant - // + span: $DIR/issue-72181.rs:24:13: 24:32 - // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(<ZST>) } - } - - bb1: { - StorageDead(_1); // scope 0 at $DIR/issue-72181.rs:+1:34: +1:35 - StorageLive(_2); // scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 - StorageLive(_3); // scope 1 at $DIR/issue-72181.rs:+3:14: +3:27 - _3 = Foo { a: const 42_u64 }; // scope 1 at $DIR/issue-72181.rs:+3:14: +3:27 - StorageLive(_4); // scope 1 at $DIR/issue-72181.rs:+3:29: +3:42 - _4 = Foo { a: const 10_u64 }; // scope 1 at $DIR/issue-72181.rs:+3:29: +3:42 - _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:+3:13: +3:43 - StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:+3:42: +3:43 - StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:+3:42: +3:43 - FakeRead(ForLet(None), _2); // scope 1 at $DIR/issue-72181.rs:+3:9: +3:10 - StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:+4:13: +4:30 - StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:+4:24: +4:25 - _6 = const 0_usize; // scope 4 at $DIR/issue-72181.rs:+4:24: +4:25 - _7 = Len(_2); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 - _8 = Lt(_6, _7); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb2, unwind: bb3]; // scope 4 at $DIR/issue-72181.rs:+4:22: +4:26 - } - - bb2: { - _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue-72181.rs:+4:22: +4:28 - StorageDead(_6); // scope 2 at $DIR/issue-72181.rs:+4:30: +4:31 - StorageDead(_5); // scope 2 at $DIR/issue-72181.rs:+4:30: +4:31 - _0 = const (); // scope 0 at $DIR/issue-72181.rs:+0:11: +5:2 - StorageDead(_2); // scope 1 at $DIR/issue-72181.rs:+5:1: +5:2 - return; // scope 0 at $DIR/issue-72181.rs:+5:2: +5:2 - } - - bb3 (cleanup): { - resume; // scope 0 at $DIR/issue-72181.rs:+0:1: +5:2 - } -} diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.mir index 425906f84fc..425906f84fc 100644 --- a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir +++ b/src/test/mir-opt/issue_72181.main.mir_map.0.mir diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff deleted file mode 100644 index ac7fe31f3b3..00000000000 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ /dev/null @@ -1,161 +0,0 @@ -- // MIR for `main` before SimplifyArmIdentity -+ // MIR for `main` after SimplifyArmIdentity - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:+2:9: +2:16 - let _4: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:+3:17: +3:23 - let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:+6:22: +6:27 - let _8: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _9: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _12: i32; // in scope 0 at $DIR/issue-73223.rs:+7:23: +7:24 - let mut _15: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _16: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _27: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - scope 3 { - debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 - let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 4 { - debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _20: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _20; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - } - } - } - scope 2 { - debug v => _4; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - goto -> bb3; // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30 - } - - bb1: { - nop; // scope 0 at $DIR/issue-73223.rs:+3:17: +3:23 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - - bb2: { - unreachable; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - } - - bb3: { - StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _4; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:+6:22: +6:27 - _7 = _1; // scope 1 at $DIR/issue-73223.rs:+6:22: +6:27 - Deinit(_6); // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:+6:17: +6:28 - StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:+6:27: +6:28 - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _13 = (_9.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = (_9.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb4: { - StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _21 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) } - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - } - - bb5: { - nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - nop; // scope 0 at $DIR/issue-73223.rs:+0:11: +8:2 - StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index ac7fe31f3b3..ac7fe31f3b3 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff diff --git a/src/test/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff new file mode 100644 index 00000000000..d9898d8e0f0 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff @@ -0,0 +1,26 @@ +- // MIR for `assume` before LowerIntrinsics ++ // MIR for `assume` after LowerIntrinsics + + fn assume() -> () { + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17 + let _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+2:9: +2:38 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 +- _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 +- // mir::Constant +- // + span: $DIR/lower_intrinsics.rs:72:9: 72:32 +- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) } ++ assume(const true); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 ++ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 + } + + bb1: { + StorageDead(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:38: +2:39 + _0 = const (); // scope 1 at $DIR/lower_intrinsics.rs:+1:5: +3:6 + return; // scope 0 at $DIR/lower_intrinsics.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff new file mode 100644 index 00000000000..4fb6752b619 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff @@ -0,0 +1,72 @@ +- // MIR for `f_copy_nonoverlapping` before LowerIntrinsics ++ // MIR for `f_copy_nonoverlapping` after LowerIntrinsics + + fn f_copy_nonoverlapping() -> () { + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:32: +0:32 + let _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12 + let _3: (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:9: +4:95 + let mut _4: *const i32; // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:59 + let mut _5: *const (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:45 + let mut _6: *const (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:45 + let _7: &(); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:33 + let mut _8: *mut i32; // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:91 + let mut _9: *mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:79 + let mut _10: *mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:79 + let mut _11: &mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:69 + scope 1 { + debug src => _1; // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:12 + let mut _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16 + scope 2 { + debug dst => _2; // in scope 2 at $DIR/lower_intrinsics.rs:+2:9: +2:16 + scope 3 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12 + Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16 + Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21 + StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 + StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59 + StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45 + StorageLive(_6); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45 + StorageLive(_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33 + _7 = &_1; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33 + _6 = &raw const (*_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33 + _5 = _6; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45 + _4 = move _5 as *const i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59 + StorageDead(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:58: +4:59 + StorageLive(_8); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91 + StorageLive(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79 + StorageLive(_10); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79 + StorageLive(_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69 + _11 = &mut _2; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69 + _10 = &raw mut (*_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69 + _9 = _10; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79 + _8 = move _9 as *mut i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91 + StorageDead(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91 +- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 +- // mir::Constant +- // + span: $DIR/lower_intrinsics.rs:65:9: 65:28 +- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) } ++ copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 ++ goto -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 + } + + bb1: { + StorageDead(_8); // scope 3 at $DIR/lower_intrinsics.rs:+4:94: +4:95 + StorageDead(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:94: +4:95 + StorageDead(_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96 + StorageDead(_10); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96 + StorageDead(_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96 + StorageDead(_6); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96 + StorageDead(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96 + _0 = const (); // scope 3 at $DIR/lower_intrinsics.rs:+3:5: +5:6 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:+6:1: +6:2 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+6:1: +6:2 + return; // scope 0 at $DIR/lower_intrinsics.rs:+6:2: +6:2 + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.rs b/src/test/mir-opt/lower_intrinsics.rs index 195543d42bb..66dae0e46b9 100644 --- a/src/test/mir-opt/lower_intrinsics.rs +++ b/src/test/mir-opt/lower_intrinsics.rs @@ -1,7 +1,7 @@ // unit-test: LowerIntrinsics // ignore-wasm32 compiled with panic=abort by default -#![feature(core_intrinsics)] +#![feature(core_intrinsics, intrinsics)] #![crate_type = "lib"] // EMIT_MIR lower_intrinsics.wrapping.LowerIntrinsics.diff @@ -51,3 +51,24 @@ pub fn discriminant<T>(t: T) { core::intrinsics::discriminant_value(&()); core::intrinsics::discriminant_value(&E::B); } + +extern "rust-intrinsic" { + // Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function + fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); +} + +// EMIT_MIR lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff +pub fn f_copy_nonoverlapping() { + let src = (); + let mut dst = (); + unsafe { + copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0); + } +} + +// EMIT_MIR lower_intrinsics.assume.LowerIntrinsics.diff +pub fn assume() { + unsafe { + std::intrinsics::assume(true); + } +} diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff deleted file mode 100644 index f9eeb1ea5b9..00000000000 --- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff +++ /dev/null @@ -1,88 +0,0 @@ -- // MIR for `bar` before MatchBranchSimplification -+ // MIR for `bar` after MatchBranchSimplification - - fn bar(_1: i32) -> (bool, bool, bool, bool) { - debug i => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:9 - let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:19: +0:43 - let _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:10 - let _6: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+6:5: +21:6 - let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+23:6: +23:7 - let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+23:9: +23:10 - let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+23:12: +23:13 - let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+23:15: +23:16 -+ let mut _11: i32; // in scope 0 at $DIR/matches_reduce_branches.rs:+6:5: +6:12 - scope 1 { - debug a => _2; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:10 - let _3: bool; // in scope 1 at $DIR/matches_reduce_branches.rs:+2:9: +2:10 - scope 2 { - debug b => _3; // in scope 2 at $DIR/matches_reduce_branches.rs:+2:9: +2:10 - let _4: bool; // in scope 2 at $DIR/matches_reduce_branches.rs:+3:9: +3:10 - scope 3 { - debug c => _4; // in scope 3 at $DIR/matches_reduce_branches.rs:+3:9: +3:10 - let _5: bool; // in scope 3 at $DIR/matches_reduce_branches.rs:+4:9: +4:10 - scope 4 { - debug d => _5; // in scope 4 at $DIR/matches_reduce_branches.rs:+4:9: +4:10 - } - } - } - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:10 - StorageLive(_3); // scope 1 at $DIR/matches_reduce_branches.rs:+2:9: +2:10 - StorageLive(_4); // scope 2 at $DIR/matches_reduce_branches.rs:+3:9: +3:10 - StorageLive(_5); // scope 3 at $DIR/matches_reduce_branches.rs:+4:9: +4:10 - StorageLive(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +21:6 -- switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12 -- } -- -- bb1: { -- _2 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+15:13: +15:21 -- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22 -- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22 -- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21 -- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 -- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 -- } -- -- bb2: { -- _2 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+8:13: +8:22 -- _3 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21 -+ StorageLive(_11); // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12 -+ _11 = _1; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12 -+ _2 = Ne(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+8:13: +8:22 -+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21 - _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22 - _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21 - Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 -- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 -- } -- -- bb3: { -+ StorageDead(_11); // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12 - StorageDead(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+21:6: +21:7 - StorageLive(_7); // scope 4 at $DIR/matches_reduce_branches.rs:+23:6: +23:7 - _7 = _2; // scope 4 at $DIR/matches_reduce_branches.rs:+23:6: +23:7 - StorageLive(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:9: +23:10 - _8 = _3; // scope 4 at $DIR/matches_reduce_branches.rs:+23:9: +23:10 - StorageLive(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13 - _9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13 - StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16 - _10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16 - Deinit(_0); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 - StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 - StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 - StorageDead(_7); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 - StorageDead(_5); // scope 3 at $DIR/matches_reduce_branches.rs:+24:1: +24:2 - StorageDead(_4); // scope 2 at $DIR/matches_reduce_branches.rs:+24:1: +24:2 - StorageDead(_3); // scope 1 at $DIR/matches_reduce_branches.rs:+24:1: +24:2 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+24:1: +24:2 - return; // scope 0 at $DIR/matches_reduce_branches.rs:+24:2: +24:2 - } - } - diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff index f9eeb1ea5b9..f9eeb1ea5b9 100644 --- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff deleted file mode 100644 index 0b40b3be8bd..00000000000 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff +++ /dev/null @@ -1,55 +0,0 @@ -- // MIR for `foo` before MatchBranchSimplification -+ // MIR for `foo` after MatchBranchSimplification - - fn foo(_1: Option<()>) -> () { - debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 - let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 -+ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - - bb0: { - StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 -- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb1: { -- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- } -- -- bb2: { -- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- } -- -- bb3: { -- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- } -- -- bb4: { - Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 -+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 - } - -- bb5: { -+ bb2: { - _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 -+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 - } - -- bb6: { -+ bb3: { - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6 - return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff index 0b40b3be8bd..0b40b3be8bd 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff deleted file mode 100644 index b8c7722cd37..00000000000 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff +++ /dev/null @@ -1,113 +0,0 @@ -- // MIR for `match_nested_if` before MatchBranchSimplification -+ // MIR for `match_nested_if` after MatchBranchSimplification - - fn match_nested_if() -> bool { - let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29 - let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - let mut _2: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 - let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 - let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 - let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -+ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -+ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 - scope 1 { - debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 - Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 - StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 - StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 - StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - _6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -- } -- -- bb1: { -- _5 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -- } -- -- bb2: { -- _5 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -- } -- -- bb3: { -+ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ _7 = move _6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 -+ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50 -+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28 - StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52 -- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -- } -- -- bb4: { -- _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -- } -- -- bb5: { -- _4 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -- } -- -- bb6: { -+ StorageLive(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -+ _8 = move _5; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 -+ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74 -+ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 - StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76 -- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -- } -- -- bb7: { -- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 -- } -- -- bb8: { -- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 -- } -- -- bb9: { -- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 -- } -- -- bb10: { -+ StorageLive(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -+ _9 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -+ _3 = Ne(_9, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18 -+ StorageDead(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 -+ StorageLive(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 -+ _10 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 - StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 - StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 -- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 -- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17 -- } -- -- bb11: { -- StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 -- StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10 -- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -- } -- -- bb12: { -+ _1 = Ne(_10, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19 -+ StorageDead(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7 - _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8 - StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2 - return; // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2 - } - } - diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff index b8c7722cd37..b8c7722cd37 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs index c122b4c69d1..a81d5f7b4e8 100644 --- a/src/test/mir-opt/matches_reduce_branches.rs +++ b/src/test/mir-opt/matches_reduce_branches.rs @@ -1,6 +1,6 @@ // unit-test: MatchBranchSimplification -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff // EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff // EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff deleted file mode 100644 index 1b4dddc1d43..00000000000 --- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `exhaustive_match` before MatchBranchSimplification -+ // MIR for `exhaustive_match` after MatchBranchSimplification - - fn exhaustive_match(_1: E) -> u8 { - debug e => _1; // in scope 0 at $DIR/matches_u8.rs:+0:25: +0:26 - let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:+0:34: +0:36 - let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:+2:9: +2:13 - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12 - } - - bb1: { - _0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18 - goto -> bb4; // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18 - } - - bb2: { - unreachable; // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12 - } - - bb3: { - _0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18 - goto -> bb4; // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18 - } - - bb4: { - return; // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 1b4dddc1d43..1b4dddc1d43 100644 --- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff deleted file mode 100644 index 6e734852e1a..00000000000 --- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `exhaustive_match_i8` before MatchBranchSimplification -+ // MIR for `exhaustive_match_i8` after MatchBranchSimplification - - fn exhaustive_match_i8(_1: E) -> i8 { - debug e => _1; // in scope 0 at $DIR/matches_u8.rs:+0:28: +0:29 - let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:+0:37: +0:39 - let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:+2:9: +2:13 - - bb0: { - _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12 - } - - bb1: { - _0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18 - goto -> bb4; // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18 - } - - bb2: { - unreachable; // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12 - } - - bb3: { - _0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18 - goto -> bb4; // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18 - } - - bb4: { - return; // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 6e734852e1a..6e734852e1a 100644 --- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/matches_u8.rs b/src/test/mir-opt/matches_u8.rs index 2c748b02a8b..422c3a95e8e 100644 --- a/src/test/mir-opt/matches_u8.rs +++ b/src/test/mir-opt/matches_u8.rs @@ -1,6 +1,6 @@ // unit-test: MatchBranchSimplification -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs index 6c2e265d514..cb652426090 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed-struct-drop-aligned.rs @@ -1,6 +1,6 @@ // ignore-wasm32-bare compiled with panic=abort by default -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir fn main() { let mut x = Packed(Aligned(Droppy(0))); diff --git a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir deleted file mode 100644 index f9ed1036f00..00000000000 --- a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir +++ /dev/null @@ -1,60 +0,0 @@ -// MIR for `main` after SimplifyCfg-elaborate-drops - -fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:11: +0:11 - let mut _1: Packed; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 - let mut _2: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - let mut _3: Droppy; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - let mut _4: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - let mut _5: Droppy; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - let mut _6: Aligned; // in scope 0 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - scope 1 { - debug x => _1; // in scope 1 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - StorageLive(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - Deinit(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:32: +1:41 - Deinit(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:24: +1:42 - StorageDead(_3); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:41: +1:42 - Deinit(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:17: +1:43 - (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:17: +1:43 - StorageDead(_2); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+1:42: +1:43 - StorageLive(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - StorageLive(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - Deinit(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:19: +2:28 - Deinit(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:11: +2:29 - StorageDead(_5); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:28: +2:29 - StorageLive(_6); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - _6 = move (_1.0: Aligned); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - drop(_6) -> [return: bb4, unwind: bb3]; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - } - - bb1: { - StorageDead(_1); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 - return; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:2: +3:2 - } - - bb2 (cleanup): { - resume; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:1: +3:2 - } - - bb3 (cleanup): { - (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - drop(_1) -> bb2; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 - } - - bb4: { - StorageDead(_6); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:5: +2:8 - StorageDead(_4); // scope 1 at $DIR/packed-struct-drop-aligned.rs:+2:28: +2:29 - _0 = const (); // scope 0 at $DIR/packed-struct-drop-aligned.rs:+0:11: +3:2 - drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/packed-struct-drop-aligned.rs:+3:1: +3:2 - } -} diff --git a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.32bit.mir b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir index f9ed1036f00..f9ed1036f00 100644 --- a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.32bit.mir +++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff b/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff deleted file mode 100644 index 28536dc28a7..00000000000 --- a/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff +++ /dev/null @@ -1,146 +0,0 @@ -- // MIR for `identity` before ConstProp -+ // MIR for `identity` after ConstProp - - fn identity(_1: Result<i32, i32>) -> Result<i32, i32> { - debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:+0:13: +0:14 - let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:+0:37: +0:53 - let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - let mut _5: isize; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - scope 1 { - debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10 - scope 2 { - scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10 - debug residual => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let _16: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _17: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - scope 9 { - debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL - debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - } - } - } - } - } - scope 3 { - debug val => _9; // in scope 3 at $DIR/separate_const_switch.rs:+1:8: +1:10 - scope 4 { - } - } - scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10 - debug self => _4; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _10: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let _11: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let _13: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _15: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - scope 6 { - debug v => _11; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - } - scope 7 { - debug e => _13; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - } - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - _4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - _10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - } - - bb1: { - StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - _9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - _2 = _9; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } - - bb2: { - unreachable; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - } - - bb3: { - StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - _8 = _6; // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - _16 = move ((_8 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } - - bb4: { - StorageLive(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - _13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - _15 = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_14 as Err).0: i32) = move _15; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_14) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 -- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ _5 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ switchInt(const 1_isize) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - } - - bb5: { - unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - } - - bb6: { - StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - _11 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - _12 = move _11; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Continue).0: i32) = move _12; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 -- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ _5 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ switchInt(const 0_isize) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - } - } - diff --git a/src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir deleted file mode 100644 index df20f0ed36b..00000000000 --- a/src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir +++ /dev/null @@ -1,124 +0,0 @@ -// MIR for `identity` after PreCodegen - -fn identity(_1: Result<i32, i32>) -> Result<i32, i32> { - debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:+0:13: +0:14 - let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:+0:37: +0:53 - let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - let _5: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let mut _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - let _7: i32; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - scope 1 { - debug residual => _5; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10 - scope 2 { - scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10 - debug residual => _6; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let _14: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _15: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _16: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - scope 9 { - debug e => _14; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL - debug t => _16; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - } - } - } - } - } - scope 3 { - debug val => _7; // in scope 3 at $DIR/separate_const_switch.rs:+1:8: +1:10 - scope 4 { - } - } - scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10 - debug self => _4; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _8: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let _9: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _10: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let _11: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _13: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - scope 6 { - debug v => _9; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - } - scope 7 { - debug e => _11; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - } - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - _4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 - _8 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - switchInt(move _8) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - } - - bb1: { - StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - _11 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - _13 = move _11; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_12 as Err).0: i32) = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_12) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _12; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_5); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - _5 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_6); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - _6 = _5; // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - _14 = move ((_6 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_16); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - _16 = move _14; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - _15 = move _16; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - StorageDead(_16); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _15; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_6); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_5); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } - - bb2: { - unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - } - - bb3: { - StorageLive(_9); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - _9 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageLive(_10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - _10 = move _9; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Continue).0: i32) = move _10; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_9); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageLive(_7); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - _7 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 - _2 = _7; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10 - StorageDead(_7); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } -} diff --git a/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff b/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff deleted file mode 100644 index 28269165e1c..00000000000 --- a/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff +++ /dev/null @@ -1,103 +0,0 @@ -- // MIR for `too_complex` before ConstProp -+ // MIR for `too_complex` after ConstProp - - fn too_complex(_1: Result<i32, usize>) -> Option<i32> { - debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:+0:16: +0:17 - let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:+0:42: +0:53 - let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 - let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:+7:13: +7:18 - let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:+7:44: +7:45 - let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 - let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:+8:42: +8:43 - let mut _8: isize; // in scope 0 at $DIR/separate_const_switch.rs:+11:9: +11:33 - let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - let mut _10: i32; // in scope 0 at $DIR/separate_const_switch.rs:+11:42: +11:43 - let _11: usize; // in scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - scope 1 { - debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:+7:16: +7:17 - } - scope 2 { - debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:+8:17: +8:18 - } - scope 3 { - debug v => _9; // in scope 3 at $DIR/separate_const_switch.rs:+11:31: +11:32 - } - scope 4 { - debug r => _11; // in scope 4 at $DIR/separate_const_switch.rs:+12:28: +12:29 - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 - _3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16 - switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16 - } - - bb1: { - StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 - _6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 - StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43 - _7 = _6; // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43 - Deinit(_2); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 - ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 - discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 - StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44 -- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -- switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 -+ _8 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -+ switchInt(const 1_isize) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 - } - - bb2: { - unreachable; // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16 - } - - bb3: { - StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - _4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 - _5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 - Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46 - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46 -- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -- switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 -+ _8 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -+ switchInt(const 0_isize) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 - } - - bb4: { - StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - _11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 - discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 - StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 - goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 - } - - bb5: { - unreachable; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 - } - - bb6: { - StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - _9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 - _10 = _9; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 - Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44 - StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 - goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 - } - - bb7: { - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2 - } - } - diff --git a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir deleted file mode 100644 index 0ee070619e7..00000000000 --- a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir +++ /dev/null @@ -1,73 +0,0 @@ -// MIR for `too_complex` after PreCodegen - -fn too_complex(_1: Result<i32, usize>) -> Option<i32> { - debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:+0:16: +0:17 - let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:+0:42: +0:53 - let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 - let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:+7:13: +7:18 - let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:+7:44: +7:45 - let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 - let _7: i32; // in scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - let mut _8: i32; // in scope 0 at $DIR/separate_const_switch.rs:+11:42: +11:43 - let _9: usize; // in scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - scope 1 { - debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:+7:16: +7:17 - } - scope 2 { - debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:+8:17: +8:18 - } - scope 3 { - debug v => _7; // in scope 3 at $DIR/separate_const_switch.rs:+11:31: +11:32 - } - scope 4 { - debug r => _9; // in scope 4 at $DIR/separate_const_switch.rs:+12:28: +12:29 - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 - _3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16 - switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16 - } - - bb1: { - StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44 - StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 - discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 - StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 - goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 - } - - bb2: { - unreachable; // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16 - } - - bb3: { - StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - _4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 - StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 - _5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 - Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46 - StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46 - StorageLive(_7); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - _7 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 - StorageLive(_8); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 - _8 = _7; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 - Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - ((_0 as Some).0: i32) = move _8; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - StorageDead(_8); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44 - StorageDead(_7); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 - goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 - } - - bb4: { - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2 - } -} diff --git a/src/test/mir-opt/simple-match.rs b/src/test/mir-opt/simple-match.rs index 44adc55b6f7..103033c4e2b 100644 --- a/src/test/mir-opt/simple-match.rs +++ b/src/test/mir-opt/simple-match.rs @@ -1,6 +1,6 @@ // Test that we don't generate unnecessarily large MIR for very simple matches -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR simple_match.match_bool.mir_map.0.mir fn match_bool(x: bool) -> usize { match x { diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir deleted file mode 100644 index 3bef6aa0579..00000000000 --- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir +++ /dev/null @@ -1,29 +0,0 @@ -// MIR for `match_bool` 0 mir_map - -fn match_bool(_1: bool) -> usize { - debug x => _1; // in scope 0 at $DIR/simple-match.rs:+0:15: +0:16 - let mut _0: usize; // return place in scope 0 at $DIR/simple-match.rs:+0:27: +0:32 - - bb0: { - FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:+1:11: +1:12 - switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:+1:5: +1:12 - } - - bb1: { - falseEdge -> [real: bb3, imaginary: bb2]; // scope 0 at $DIR/simple-match.rs:+2:9: +2:13 - } - - bb2: { - _0 = const 20_usize; // scope 0 at $DIR/simple-match.rs:+3:14: +3:16 - goto -> bb4; // scope 0 at $DIR/simple-match.rs:+3:14: +3:16 - } - - bb3: { - _0 = const 10_usize; // scope 0 at $DIR/simple-match.rs:+2:17: +2:19 - goto -> bb4; // scope 0 at $DIR/simple-match.rs:+2:17: +2:19 - } - - bb4: { - return; // scope 0 at $DIR/simple-match.rs:+5:2: +5:2 - } -} diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir index 3bef6aa0579..3bef6aa0579 100644 --- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir +++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs index 62a15df04b1..d09bd92c4e8 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs @@ -11,5 +11,4 @@ fn main() { map(None); } -// EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff deleted file mode 100644 index 51d26b08b2a..00000000000 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff +++ /dev/null @@ -1,52 +0,0 @@ -- // MIR for `map` before SimplifyLocals -+ // MIR for `map` after SimplifyLocals - - fn map(_1: Option<Box<()>>) -> Option<Box<()>> { - debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9 - let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46 - let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13 - let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 -- let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 -- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 -- let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - scope 1 { - debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - } - - bb0: { -- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 -- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 - _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 - switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12 - } - - bb1: { - StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15 - StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26 - Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27 - StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 - StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 - goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27 - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12 - } - - bb3: { - Deinit(_0); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 - discriminant(_0) = 0; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 - goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21 - } - - bb4: { -- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2 - return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff index 51d26b08b2a..51d26b08b2a 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index 0fd32906db6..344c1af2c91 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -1,6 +1,6 @@ // compile-flags: -Zmir-opt-level=0 -// EMIT_MIR_FOR_EACH_BIT_WIDTH + // EMIT_MIR core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir fn main() { let _fn = std::ptr::drop_in_place::<[String]> as unsafe fn(_); diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir deleted file mode 100644 index b4b317e84af..00000000000 --- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir +++ /dev/null @@ -1,101 +0,0 @@ -// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops - -fn std::ptr::drop_in_place(_1: *mut [String]) -> () { - let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _4: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _14: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - - bb0: { - goto -> bb15; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb1: { - return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb2 (cleanup): { - resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb3 (cleanup): { - _5 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_5)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb4 (cleanup): { - _6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb5: { - _7 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb6: { - _8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb7: { - _4 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb8: { - goto -> bb7; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb9 (cleanup): { - _11 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_11)) -> bb10; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb10 (cleanup): { - _12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb11: { - _13 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb12: { - _14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb13: { - _15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = move _15 as *mut std::string::String (Misc); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb14: { - goto -> bb13; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb15: { - _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } -} diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.32bit.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index b4b317e84af..b4b317e84af 100644 --- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.32bit.mir +++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index 670f61cd5ce..9ef3d86472d 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -1,7 +1,7 @@ // Test that we don't ICE when trying to dump MIR for unusual item types and // that we don't create filenames containing `<` and `>` // compile-flags: -Zmir-opt-level=0 -// EMIT_MIR_FOR_EACH_BIT_WIDTH + struct A; diff --git a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.64bit.mir deleted file mode 100644 index a72e00ecde7..00000000000 --- a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.64bit.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `E::V::{constant#0}` 0 mir_map - -E::V::{constant#0}: isize = { - let mut _0: isize; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 - - bb0: { - _0 = const 5_isize; // scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:9: +0:10 - } -} diff --git a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.mir index a72e00ecde7..a72e00ecde7 100644 --- a/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.E-V-{constant#0}.mir_map.0.mir diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir deleted file mode 100644 index 0686af46ed5..00000000000 --- a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir +++ /dev/null @@ -1,12 +0,0 @@ -// MIR for `Test::X` 0 mir_map - -fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - - bb0: { - Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:6 - } -} diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.mir index 0686af46ed5..0686af46ed5 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.mir diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir deleted file mode 100644 index 7ffd242e0dc..00000000000 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir +++ /dev/null @@ -1,39 +0,0 @@ -// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops - -fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () { - let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _2: &mut std::vec::Vec<i32>; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - - bb0: { - goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb1: { - return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb2 (cleanup): { - resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb3: { - goto -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb4 (cleanup): { - drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb5: { - drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb3, unwind: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - } - - bb6: { - _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _3 = <Vec<i32> as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - // mir::Constant - // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(<ZST>) } - } -} diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index 7ffd242e0dc..7ffd242e0dc 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir deleted file mode 100644 index e2633f61b5f..00000000000 --- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` 0 mir_map - -const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = { - let mut _0: i32; // return place in scope 0 at $DIR/unusual-item-types.rs:+0:32: +0:35 - - bb0: { - _0 = const 2_i32; // scope 0 at $DIR/unusual-item-types.rs:+0:38: +0:39 - return; // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:39 - } -} diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.mir index e2633f61b5f..e2633f61b5f 100644 --- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.mir diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff deleted file mode 100644 index eef7011149d..00000000000 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff +++ /dev/null @@ -1,55 +0,0 @@ -- // MIR for `change_loop_body` before ConstProp -+ // MIR for `change_loop_body` after ConstProp - - fn change_loop_body() -> () { - let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:+0:27: +0:27 - let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 - let mut _2: (); // in scope 0 at $DIR/while_let_loops.rs:+0:1: +6:2 - let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/while_let_loops.rs:+2:28: +2:32 - let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:+2:15: +2:25 - let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:+2:33: +5:6 - let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 - let _7: (); // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 - let mut _8: !; // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 - scope 1 { - debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:+1:9: +1:15 - scope 2 { - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 - _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19 - StorageLive(_3); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - Deinit(_3); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - discriminant(_3) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 -- _4 = discriminant(_3); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 -- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 -+ _4 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 -+ switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 - } - - bb1: { - switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 - } - - bb2: { - _1 = const 1_i32; // scope 2 at $DIR/while_let_loops.rs:+3:9: +3:15 - nop; // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14 - goto -> bb4; // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14 - } - - bb3: { - StorageLive(_7); // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6 - nop; // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6 - StorageDead(_7); // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6 - goto -> bb4; // scope 1 at no-location - } - - bb4: { - StorageDead(_3); // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6 - StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:+6:1: +6:2 - return; // scope 0 at $DIR/while_let_loops.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff index eef7011149d..eef7011149d 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir deleted file mode 100644 index 15b0aece8f5..00000000000 --- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir +++ /dev/null @@ -1,17 +0,0 @@ -// MIR for `change_loop_body` after PreCodegen - -fn change_loop_body() -> () { - let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:+0:27: +0:27 - let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 - scope 1 { - debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:+1:9: +1:15 - scope 2 { - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 - StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:+6:1: +6:2 - return; // scope 0 at $DIR/while_let_loops.rs:+6:2: +6:2 - } -} diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir index 15b0aece8f5..15b0aece8f5 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir +++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir diff --git a/src/test/mir-opt/while_let_loops.rs b/src/test/mir-opt/while_let_loops.rs index f320a218c85..fc56cd6985d 100644 --- a/src/test/mir-opt/while_let_loops.rs +++ b/src/test/mir-opt/while_let_loops.rs @@ -1,6 +1,5 @@ // EMIT_MIR while_let_loops.change_loop_body.ConstProp.diff // EMIT_MIR while_let_loops.change_loop_body.PreCodegen.after.mir -// EMIT_MIR_FOR_EACH_BIT_WIDTH pub fn change_loop_body() { let mut _x = 0; diff --git a/src/test/run-make/track-pgo-dep-info/Makefile b/src/test/run-make/track-pgo-dep-info/Makefile new file mode 100644 index 00000000000..60b59c04aa9 --- /dev/null +++ b/src/test/run-make/track-pgo-dep-info/Makefile @@ -0,0 +1,26 @@ +# needs-profiler-support +# ignore-windows-gnu + +-include ../../run-make-fulldeps/tools.mk + +# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC` +# instead of hardcoding them everywhere they're needed. +ifeq ($(IS_MUSL_HOST),1) +ADDITIONAL_ARGS := $(RUSTFLAGS) +endif + +all: + # Generate PGO profiles + $(BARE_RUSTC) $(ADDITIONAL_ARGS) -Cprofile-generate=$(TMPDIR)/profiles --out-dir $(TMPDIR) main.rs + $(TMPDIR)/main + + # Merge profiles + "$(LLVM_BIN_DIR)/llvm-profdata" merge \ + -o "$(TMPDIR)/merged.profdata" \ + "$(TMPDIR)/profiles" || exit 1 + + # Use the profile + $(RUSTC) -Cprofile-use=$(TMPDIR)/merged.profdata --emit dep-info main.rs + + # Check that profile file is in depinfo + $(CGREP) "merged.profdata" < $(TMPDIR)/main.d diff --git a/src/test/run-make/track-pgo-dep-info/main.rs b/src/test/run-make/track-pgo-dep-info/main.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/src/test/run-make/track-pgo-dep-info/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/rustdoc-json/enum_variant_hidden.rs b/src/test/rustdoc-json/enums/field_hidden.rs index c5e063a055c..e6310cc3b99 100644 --- a/src/test/rustdoc-json/enum_variant_hidden.rs +++ b/src/test/rustdoc-json/enums/field_hidden.rs @@ -6,7 +6,7 @@ // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [null] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/src/test/rustdoc-json/enums/kind.rs b/src/test/rustdoc-json/enums/kind.rs new file mode 100644 index 00000000000..e9ea3ae23c2 --- /dev/null +++ b/src/test/rustdoc-json/enums/kind.rs @@ -0,0 +1,37 @@ +// ignore-tidy-linelength + +#![feature(no_core)] +#![no_core] + +pub enum Foo { + // @set Unit = "$.index[*][?(@.name=='Unit')].id" + // @is "$.index[*][?(@.name=='Unit')].inner.variant_kind" '"plain"' + // @is "$.index[*][?(@.name=='Unit')].inner.variant_inner" null + Unit, + // @set Named = "$.index[*][?(@.name=='Named')].id" + // @is "$.index[*][?(@.name=='Named')].inner.variant_kind" '"struct"' + // @is "$.index[*][?(@.name=='Named')].inner.variant_inner" '{"fields": [], "fields_stripped": false}' + Named {}, + // @set Tuple = "$.index[*][?(@.name=='Tuple')].id" + // @is "$.index[*][?(@.name=='Tuple')].inner.variant_kind" '"tuple"' + // @is "$.index[*][?(@.name=='Tuple')].inner.variant_inner" [] + Tuple(), + // @set NamedField = "$.index[*][?(@.name=='NamedField')].id" + // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id" + // @is "$.index[*][?(@.name=='NamedField')].inner.variant_kind" '"struct"' + // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields[*]" $x + // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields_stripped" false + NamedField { x: i32 }, + // @set TupleField = "$.index[*][?(@.name=='TupleField')].id" + // @is "$.index[*][?(@.name=='TupleField')].inner.variant_kind" '"tuple"' + // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id" + // @is "$.index[*][?(@.name=='TupleField')].inner.variant_inner[*]" $tup_field + TupleField(i32), +} + +// @is "$.index[*][?(@.name=='Foo')].inner.variants[0]" $Unit +// @is "$.index[*][?(@.name=='Foo')].inner.variants[1]" $Named +// @is "$.index[*][?(@.name=='Foo')].inner.variants[2]" $Tuple +// @is "$.index[*][?(@.name=='Foo')].inner.variants[3]" $NamedField +// @is "$.index[*][?(@.name=='Foo')].inner.variants[4]" $TupleField +// @count "$.index[*][?(@.name=='Foo')].inner.variants[*]" 5 diff --git a/src/test/rustdoc-json/enums/struct_field_hidden.rs b/src/test/rustdoc-json/enums/struct_field_hidden.rs new file mode 100644 index 00000000000..f612a34a492 --- /dev/null +++ b/src/test/rustdoc-json/enums/struct_field_hidden.rs @@ -0,0 +1,17 @@ +pub enum Foo { + Variant { + #[doc(hidden)] + a: i32, + // @set b = "$.index[*][?(@.name=='b')].id" + b: i32, + #[doc(hidden)] + x: i32, + // @set y = "$.index[*][?(@.name=='y')].id" + y: i32, + }, + // @is "$.index[*][?(@.name=='Variant')].inner.variant_kind" '"struct"' + // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields_stripped" true + // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[0]" $b + // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[1]" $y + // @count "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[*]" 2 +} diff --git a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs new file mode 100644 index 00000000000..f546eaa0d17 --- /dev/null +++ b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs @@ -0,0 +1,94 @@ +#![feature(no_core)] +#![no_core] + +// @set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id" +// @set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id" +// @set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id" +// @set 2.2.1 = "$.index[*][?(@.docs=='2.2.1')].id" +// @set 2.3.0 = "$.index[*][?(@.docs=='2.3.0')].id" +// @set 3.1.1 = "$.index[*][?(@.docs=='3.1.1')].id" +// @set 3.1.2 = "$.index[*][?(@.docs=='3.1.2')].id" +// @set 3.2.0 = "$.index[*][?(@.docs=='3.2.0')].id" +// @set 3.2.2 = "$.index[*][?(@.docs=='3.2.2')].id" +// @set 3.3.0 = "$.index[*][?(@.docs=='3.3.0')].id" +// @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id" + +pub enum EnumWithStrippedTupleVariants { + // @is "$.index[*][?(@.name=='None')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='None')].inner.variant_inner[*]" 0 + None(), + + // @is "$.index[*][?(@.name=='One')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='One')].inner.variant_inner[*]" 1 + // @is "$.index[*][?(@.name=='One')].inner.variant_inner[0]" $1.1.0 + One(/** 1.1.0*/ bool), + // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[*]" 1 + // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[0]" null + OneHidden(#[doc(hidden)] bool), + + // @is "$.index[*][?(@.name=='Two')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='Two')].inner.variant_inner[*]" 2 + // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[0]" $2.1.0 + // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[1]" $2.1.1 + Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool), + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[*]" 2 + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[0]" null + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[1]" $2.2.1 + TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool), + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[*]" 2 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[0]" $2.3.0 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[1]" null + TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool), + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[*]" 2 + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[0]" null + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[1]" null + TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool), + + // @is "$.index[*][?(@.name=='Three1')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='Three1')].inner.variant_inner[*]" 3 + // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[0]" null + // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[1]" $3.1.1 + // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[2]" $3.1.2 + Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool), + // @is "$.index[*][?(@.name=='Three2')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='Three2')].inner.variant_inner[*]" 3 + // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[0]" $3.2.0 + // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[1]" null + // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[2]" $3.2.2 + Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool), + // @is "$.index[*][?(@.name=='Three3')].inner.variant_kind" '"tuple"' + // @count "$.index[*][?(@.name=='Three3')].inner.variant_inner[*]" 3 + // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[0]" $3.3.0 + // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[1]" $3.3.1 + // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[2]" null + Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool), +} + + +// @is "$.index[*][?(@.docs=='1.1.0')].name" '"0"' +// @is "$.index[*][?(@.docs=='2.1.0')].name" '"0"' +// @is "$.index[*][?(@.docs=='2.1.1')].name" '"1"' +// @is "$.index[*][?(@.docs=='2.2.1')].name" '"1"' +// @is "$.index[*][?(@.docs=='2.3.0')].name" '"0"' +// @is "$.index[*][?(@.docs=='3.1.1')].name" '"1"' +// @is "$.index[*][?(@.docs=='3.1.2')].name" '"2"' +// @is "$.index[*][?(@.docs=='3.2.0')].name" '"0"' +// @is "$.index[*][?(@.docs=='3.2.2')].name" '"2"' +// @is "$.index[*][?(@.docs=='3.3.0')].name" '"0"' +// @is "$.index[*][?(@.docs=='3.3.1')].name" '"1"' + +// @is "$.index[*][?(@.docs=='1.1.0')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='2.1.0')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='2.1.1')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='2.2.1')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='2.3.0')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.1.1')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.1.2')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.2.0')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.2.2')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.3.0')].inner" '{"kind": "primitive", "inner": "bool"}' +// @is "$.index[*][?(@.docs=='3.3.1')].inner" '{"kind": "primitive", "inner": "bool"}' diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index 73ec9392ce9..ee2d2efa960 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -17,7 +17,7 @@ pub mod l1 { pub mod l3 { // @is "$.index[*][?(@.name=='L4')].kind" \"struct\" - // @is "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" + // @is "$.index[*][?(@.name=='L4')].inner.kind" \"unit\" // @set l4_id = "$.index[*][?(@.name=='L4')].id" // @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; diff --git a/src/test/rustdoc-json/structs/plain_all_pub.rs b/src/test/rustdoc-json/structs/plain_all_pub.rs new file mode 100644 index 00000000000..b86ab93c264 --- /dev/null +++ b/src/test/rustdoc-json/structs/plain_all_pub.rs @@ -0,0 +1,11 @@ +pub struct Demo { + pub x: i32, + pub y: i32, +} + +// @set x = "$.index[*][?(@.name=='x')].id" +// @set y = "$.index[*][?(@.name=='y')].id" +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[1]" $y +// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 2 +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" false diff --git a/src/test/rustdoc-json/structs/plain_doc_hidden.rs b/src/test/rustdoc-json/structs/plain_doc_hidden.rs new file mode 100644 index 00000000000..7800b55a481 --- /dev/null +++ b/src/test/rustdoc-json/structs/plain_doc_hidden.rs @@ -0,0 +1,11 @@ +pub struct Demo { + pub x: i32, + #[doc(hidden)] + pub y: i32, +} + +// @set x = "$.index[*][?(@.name=='x')].id" +// @!has "$.index[*][?(@.name=='y')].id" +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x +// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1 +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true diff --git a/src/test/rustdoc-json/structs/plain_empty.rs b/src/test/rustdoc-json/structs/plain_empty.rs index 2ad9e86096c..1d01b8bc14a 100644 --- a/src/test/rustdoc-json/structs/plain_empty.rs +++ b/src/test/rustdoc-json/structs/plain_empty.rs @@ -1,6 +1,5 @@ -// @has "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" -// @has "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\" -// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\" -// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false -// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields" [] +// @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" +// @is "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\" +// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields_stripped" false +// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields" [] pub struct PlainEmpty {} diff --git a/src/test/rustdoc-json/structs/plain_pub_priv.rs b/src/test/rustdoc-json/structs/plain_pub_priv.rs new file mode 100644 index 00000000000..9b771224d97 --- /dev/null +++ b/src/test/rustdoc-json/structs/plain_pub_priv.rs @@ -0,0 +1,9 @@ +pub struct Demo { + pub x: i32, + y: i32, +} + +// @set x = "$.index[*][?(@.name=='x')].id" +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x +// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1 +// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true diff --git a/src/test/rustdoc-json/structs/tuple.rs b/src/test/rustdoc-json/structs/tuple.rs index 91fac359422..6bdb753ee01 100644 --- a/src/test/rustdoc-json/structs/tuple.rs +++ b/src/test/rustdoc-json/structs/tuple.rs @@ -1,5 +1,4 @@ -// @has "$.index[*][?(@.name=='Tuple')].visibility" \"public\" -// @has "$.index[*][?(@.name=='Tuple')].kind" \"struct\" -// @has "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\" -// @has "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true +// @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\" +// @is "$.index[*][?(@.name=='Tuple')].kind" \"struct\" +// @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" '[null, null]' pub struct Tuple(u32, String); diff --git a/src/test/rustdoc-json/structs/tuple_empty.rs b/src/test/rustdoc-json/structs/tuple_empty.rs new file mode 100644 index 00000000000..0ad6a89547f --- /dev/null +++ b/src/test/rustdoc-json/structs/tuple_empty.rs @@ -0,0 +1,2 @@ +// @is "$.index[*][?(@.name=='TupleUnit')].inner.kind.tuple" [] +pub struct TupleUnit(); diff --git a/src/test/rustdoc-json/structs/tuple_pub_priv.rs b/src/test/rustdoc-json/structs/tuple_pub_priv.rs new file mode 100644 index 00000000000..9d5a1d1c8be --- /dev/null +++ b/src/test/rustdoc-json/structs/tuple_pub_priv.rs @@ -0,0 +1,13 @@ +pub struct Demo( + i32, + /// field + pub i32, + #[doc(hidden)] i32, +); + +// @set field = "$.index[*][?(@.docs=='field')].id" + +// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[0]" null +// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[1]" $field +// @is "$.index[*][?(@.name=='Demo')].inner.kind.tuple[2]" null +// @count "$.index[*][?(@.name=='Demo')].inner.kind.tuple[*]" 3 diff --git a/src/test/rustdoc-json/structs/unit.rs b/src/test/rustdoc-json/structs/unit.rs index 85a515b5e78..26570971721 100644 --- a/src/test/rustdoc-json/structs/unit.rs +++ b/src/test/rustdoc-json/structs/unit.rs @@ -1,5 +1,4 @@ -// @has "$.index[*][?(@.name=='Unit')].visibility" \"public\" -// @has "$.index[*][?(@.name=='Unit')].kind" \"struct\" -// @has "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\" -// @has "$.index[*][?(@.name=='Unit')].inner.fields" [] +// @is "$.index[*][?(@.name=='Unit')].visibility" \"public\" +// @is "$.index[*][?(@.name=='Unit')].kind" \"struct\" +// @is "$.index[*][?(@.name=='Unit')].inner.kind" \"unit\" pub struct Unit; diff --git a/src/test/rustdoc-json/structs/with_generics.rs b/src/test/rustdoc-json/structs/with_generics.rs index b0ad1883f8a..00474800a0e 100644 --- a/src/test/rustdoc-json/structs/with_generics.rs +++ b/src/test/rustdoc-json/structs/with_generics.rs @@ -1,13 +1,13 @@ use std::collections::HashMap; -// @has "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\" -// @has "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\" -// @has "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true +// @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\" +// @is "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\" +// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\" +// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type.bounds" [] +// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\" +// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type.bounds" [] +// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields_stripped" true +// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields" [] pub struct WithGenerics<T, U> { stuff: Vec<T>, things: HashMap<U, U>, diff --git a/src/test/rustdoc-json/structs/with_primitives.rs b/src/test/rustdoc-json/structs/with_primitives.rs index b74050dde78..9c5a37f3957 100644 --- a/src/test/rustdoc-json/structs/with_primitives.rs +++ b/src/test/rustdoc-json/structs/with_primitives.rs @@ -1,9 +1,9 @@ -// @has "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" -// @has "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\" -// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\" -// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" [] -// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\" -// @has "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true +// @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" +// @is "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\" +// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\" +// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" [] +// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields_stripped" true +// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields" [] pub struct WithPrimitives<'a> { num: u32, s: &'a str, diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs index 0e449256153..e9e809fa416 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs @@ -11,9 +11,11 @@ extern crate rustc_macros; extern crate rustc_session; extern crate rustc_span; -use rustc_errors::{AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, fluent}; +use rustc_errors::{ + AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, fluent +}; use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; -use rustc_session::{parse::ParseSess, SessionDiagnostic}; +use rustc_session::SessionDiagnostic; use rustc_span::Span; #[derive(SessionDiagnostic)] @@ -33,8 +35,8 @@ struct Note { pub struct UntranslatableInSessionDiagnostic; impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for UntranslatableInSessionDiagnostic { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - sess.struct_err("untranslatable diagnostic") + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + handler.struct_err("untranslatable diagnostic") //~^ ERROR diagnostics should be created using translatable messages } } @@ -42,8 +44,8 @@ impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for UntranslatableInSessionDiagn pub struct TranslatableInSessionDiagnostic; impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for TranslatableInSessionDiagnostic { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - sess.struct_err(fluent::parser::expect_path) + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + handler.struct_err(fluent::parser::expect_path) } } @@ -64,11 +66,11 @@ impl AddSubdiagnostic for TranslatableInAddSubdiagnostic { } } -pub fn make_diagnostics<'a>(sess: &'a ParseSess) { - let _diag = sess.struct_err(fluent::parser::expect_path); +pub fn make_diagnostics<'a>(handler: &'a Handler) { + let _diag = handler.struct_err(fluent::parser::expect_path); //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls - let _diag = sess.struct_err("untranslatable diagnostic"); + let _diag = handler.struct_err("untranslatable diagnostic"); //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls //~^^ ERROR diagnostics should be created using translatable messages } @@ -76,6 +78,6 @@ pub fn make_diagnostics<'a>(sess: &'a ParseSess) { // Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted. #[rustc_lint_diagnostics] -pub fn skipped_because_of_annotation<'a>(sess: &'a ParseSess) { - let _diag = sess.struct_err("untranslatable diagnostic"); // okay! +pub fn skipped_because_of_annotation<'a>(handler: &'a Handler) { + let _diag = handler.struct_err("untranslatable diagnostic"); // okay! } diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr index ed5105dabcd..e5c5bc2e998 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:37:14 + --> $DIR/diagnostics.rs:39:17 | -LL | sess.struct_err("untranslatable diagnostic") - | ^^^^^^^^^^ +LL | handler.struct_err("untranslatable diagnostic") + | ^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:6:9 @@ -11,16 +11,16 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:54:14 + --> $DIR/diagnostics.rs:56:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls - --> $DIR/diagnostics.rs:68:22 + --> $DIR/diagnostics.rs:70:25 | -LL | let _diag = sess.struct_err(fluent::parser::expect_path); - | ^^^^^^^^^^ +LL | let _diag = handler.struct_err(fluent::parser::expect_path); + | ^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:7:9 @@ -29,16 +29,16 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls - --> $DIR/diagnostics.rs:71:22 + --> $DIR/diagnostics.rs:73:25 | -LL | let _diag = sess.struct_err("untranslatable diagnostic"); - | ^^^^^^^^^^ +LL | let _diag = handler.struct_err("untranslatable diagnostic"); + | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:71:22 + --> $DIR/diagnostics.rs:73:25 | -LL | let _diag = sess.struct_err("untranslatable diagnostic"); - | ^^^^^^^^^^ +LL | let _diag = handler.struct_err("untranslatable diagnostic"); + | ^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs index 318673ef847..972c24c23b0 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs +++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs @@ -24,7 +24,7 @@ fn main() { let _a = || { match l1 { L1::A => (), L1::B => () } }; // (except if the match is already non-exhaustive) let _b = || { match l1 { L1::A => () } }; - //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + //~^ ERROR: non-exhaustive patterns: `L1::B` not covered [E0004] // l2 should not be captured as it is a non-exhaustive SingleVariant // defined in this crate diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index e0678bc718f..3a5fad15421 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `B` not covered +error[E0004]: non-exhaustive patterns: `L1::B` not covered --> $DIR/non-exhaustive-match.rs:26:25 | LL | let _b = || { match l1 { L1::A => () } }; - | ^^ pattern `B` not covered + | ^^ pattern `L1::B` not covered | note: `L1` defined here --> $DIR/non-exhaustive-match.rs:12:14 @@ -12,8 +12,8 @@ LL | enum L1 { A, B } = note: the matched value is of type `L1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | let _b = || { match l1 { L1::A => (), B => todo!() } }; - | ++++++++++++++ +LL | let _b = || { match l1 { L1::A => (), L1::B => todo!() } }; + | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: type `E1` is non-empty --> $DIR/non-exhaustive-match.rs:37:25 diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs index 01b99134a44..3de2b1a78a3 100644 --- a/src/test/ui/empty/empty-never-array.rs +++ b/src/test/ui/empty/empty-never-array.rs @@ -8,7 +8,7 @@ enum Helper<T, U> { fn transmute<T, U>(t: T) -> U { let Helper::U(u) = Helper::T(t, []); - //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered + //~^ ERROR refutable pattern in local binding: `Helper::T(_, _)` not covered u } diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 909aa73a74a..8c80b05ee3a 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `T(_, _)` not covered +error[E0005]: refutable pattern in local binding: `Helper::T(_, _)` not covered --> $DIR/empty-never-array.rs:10:9 | LL | let Helper::U(u) = Helper::T(t, []); - | ^^^^^^^^^^^^ pattern `T(_, _)` not covered + | ^^^^^^^^^^^^ pattern `Helper::T(_, _)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/error-codes/E0004.stderr b/src/test/ui/error-codes/E0004.stderr index 8ba151d9e65..4ac8c904f05 100644 --- a/src/test/ui/error-codes/E0004.stderr +++ b/src/test/ui/error-codes/E0004.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered +error[E0004]: non-exhaustive patterns: `Terminator::HastaLaVistaBaby` not covered --> $DIR/E0004.rs:9:11 | LL | match x { - | ^ pattern `HastaLaVistaBaby` not covered + | ^ pattern `Terminator::HastaLaVistaBaby` not covered | note: `Terminator` defined here --> $DIR/E0004.rs:2:5 @@ -15,7 +15,7 @@ LL | HastaLaVistaBaby, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Terminator::TalkToMyHand => {} -LL + HastaLaVistaBaby => todo!() +LL + Terminator::HastaLaVistaBaby => todo!() | error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs index 29a6e1f8a01..9b646060adf 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -21,7 +21,7 @@ fn main() { Foo::A => {} Foo::B => {} } - //~^^^^ ERROR non-exhaustive patterns: `C` not covered + //~^^^^ ERROR non-exhaustive patterns: `Foo::C` not covered match Foo::A { Foo::A => {} diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index dbeef6c2d2a..3de08e215da 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -99,11 +99,11 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable -error[E0004]: non-exhaustive patterns: `C` not covered +error[E0004]: non-exhaustive patterns: `Foo::C` not covered --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11 | LL | match Foo::A { - | ^^^^^^ pattern `C` not covered + | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:12:15 @@ -116,7 +116,7 @@ LL | A, B, C, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo::B => {} -LL + C => todo!() +LL + Foo::C => todo!() | error: aborting due to previous error; 10 warnings emitted diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr new file mode 100644 index 00000000000..fd2e454e7e4 --- /dev/null +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied + --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr new file mode 100644 index 00000000000..c01c33a8931 --- /dev/null +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -0,0 +1,22 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - fn ice() -> impl AsRef<Fn(&())> { +LL + fn ice() -> impl AsRef<dyn Fn(&())> { + | + +error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied + --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 + | +LL | fn ice() -> impl AsRef<Fn(&())> { + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0782. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs new file mode 100644 index 00000000000..856dc7a3f5a --- /dev/null +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -0,0 +1,12 @@ +// revisions: edition2015 edition2021 +//[edition2021]edition:2021 + +#![allow(warnings)] + +fn ice() -> impl AsRef<Fn(&())> { + //~^ ERROR: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782] + todo!() +} + +fn main() {} diff --git a/src/test/ui/issue-94866.stderr b/src/test/ui/issue-94866.stderr index 5477d83f449..b3c17ce8974 100644 --- a/src/test/ui/issue-94866.stderr +++ b/src/test/ui/issue-94866.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `B` not covered +error[E0004]: non-exhaustive patterns: `Enum::B` not covered --> $DIR/issue-94866.rs:10:11 | LL | match Enum::A { - | ^^^^^^^ pattern `B` not covered + | ^^^^^^^ pattern `Enum::B` not covered | note: `Enum` defined here --> $DIR/issue-94866.rs:7:16 @@ -13,7 +13,7 @@ LL | enum Enum { A, B } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Enum::A => m!(), -LL + B => todo!() +LL + Enum::B => todo!() | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43988.stderr b/src/test/ui/issues/issue-43988.stderr index 03aa37f5207..02c5dd5bfb7 100644 --- a/src/test/ui/issues/issue-43988.stderr +++ b/src/test/ui/issues/issue-43988.stderr @@ -31,12 +31,16 @@ error[E0552]: unrecognized representation hint | LL | #[repr(nothing)] | ^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 | LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:30:5 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 6deb1f271a7..bfabe2d12f7 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 @@ -411,7 +411,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=4, }, tag_encoding: Niche { - dataful_variant: 0, + untagged_variant: 0, niche_variants: 1..=2, niche_start: 3, }, @@ -555,7 +555,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=4, }, tag_encoding: Niche { - dataful_variant: 0, + untagged_variant: 0, niche_variants: 1..=2, niche_start: 3, }, 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 56d3a52bb7f..a3e82070e0f 100644 --- a/src/test/ui/layout/zero-sized-array-enum-niche.stderr +++ b/src/test/ui/layout/zero-sized-array-enum-niche.stderr @@ -353,7 +353,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed<U16IsZero>>) = Layout { valid_range: 0..=1, }, tag_encoding: Niche { - dataful_variant: 1, + untagged_variant: 1, niche_variants: 0..=0, niche_start: 1, }, diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs new file mode 100644 index 00000000000..645bc7db0dd --- /dev/null +++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs @@ -0,0 +1,9 @@ +fn no_restriction<T>(x: &()) -> &() { + with_restriction::<T>(x) //~ ERROR the parameter type `T` may not live long enough +} + +fn with_restriction<'b, T: 'b>(x: &'b ()) -> &'b () { + x +} + +fn main() {} diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr new file mode 100644 index 00000000000..a8b0996d8b0 --- /dev/null +++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -0,0 +1,23 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5 + | +LL | with_restriction::<T>(x) + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:1:25 + | +LL | fn no_restriction<T>(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5 + | +LL | with_restriction::<T>(x) + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() { + | +++ ++++ + +error: aborting due to previous error + diff --git a/src/test/ui/match/match_non_exhaustive.rs b/src/test/ui/match/match_non_exhaustive.rs index 8219f0eb135..f162dd60f50 100644 --- a/src/test/ui/match/match_non_exhaustive.rs +++ b/src/test/ui/match/match_non_exhaustive.rs @@ -21,7 +21,7 @@ fn main() { match l { L::A => (), L::B => () }; // (except if the match is already non-exhaustive) match l { L::A => () }; - //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + //~^ ERROR: non-exhaustive patterns: `L::B` not covered [E0004] // E1 is not visibly uninhabited from here let (e1, e2) = bar(); diff --git a/src/test/ui/match/match_non_exhaustive.stderr b/src/test/ui/match/match_non_exhaustive.stderr index 9d92f8fdbb4..46ee8d5179e 100644 --- a/src/test/ui/match/match_non_exhaustive.stderr +++ b/src/test/ui/match/match_non_exhaustive.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `B` not covered +error[E0004]: non-exhaustive patterns: `L::B` not covered --> $DIR/match_non_exhaustive.rs:23:11 | LL | match l { L::A => () }; - | ^ pattern `B` not covered + | ^ pattern `L::B` not covered | note: `L` defined here --> $DIR/match_non_exhaustive.rs:10:13 @@ -12,8 +12,8 @@ LL | enum L { A, B } = note: the matched value is of type `L` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match l { L::A => (), B => todo!() }; - | ++++++++++++++ +LL | match l { L::A => (), L::B => todo!() }; + | +++++++++++++++++ error[E0004]: non-exhaustive patterns: type `E1` is non-empty --> $DIR/match_non_exhaustive.rs:28:11 diff --git a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs b/src/test/ui/parser/do-not-suggest-semicolon-before-array.rs index 7ebf3f6b0d8..7ebf3f6b0d8 100644 --- a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.rs +++ b/src/test/ui/parser/do-not-suggest-semicolon-before-array.rs diff --git a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr b/src/test/ui/parser/do-not-suggest-semicolon-before-array.stderr index d6e8db80329..a9dd526321f 100644 --- a/src/test/ui/parser/do-not-suggest-suggest-semicolon-before-array.stderr +++ b/src/test/ui/parser/do-not-suggest-semicolon-before-array.stderr @@ -1,5 +1,5 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,` - --> $DIR/do-not-suggest-suggest-semicolon-before-array.rs:5:5 + --> $DIR/do-not-suggest-semicolon-before-array.rs:5:5 | LL | [1, 3) | ^ ^ help: `]` may belong here diff --git a/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs b/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs new file mode 100644 index 00000000000..d6f7981813f --- /dev/null +++ b/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs @@ -0,0 +1,3 @@ +fn main() { + let _x = vec[1, 2, 3]; //~ ERROR expected one of `.`, `?`, `]`, or an operator +} diff --git a/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr b/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr new file mode 100644 index 00000000000..2fe6a28eeb4 --- /dev/null +++ b/src/test/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs:2:19 + | +LL | let _x = vec[1, 2, 3]; + | ^ expected one of `.`, `?`, `]`, or an operator + +error: aborting due to previous error + diff --git a/src/test/ui/parser/recover-field-semi.rs b/src/test/ui/parser/recover-field-semi.rs new file mode 100644 index 00000000000..b703578860e --- /dev/null +++ b/src/test/ui/parser/recover-field-semi.rs @@ -0,0 +1,16 @@ +struct Foo { + foo: i32; + //~^ ERROR struct fields are separated by `,` +} + +union Bar { //~ ERROR + foo: i32; + //~^ ERROR union fields are separated by `,` +} + +enum Baz { + Qux { foo: i32; } + //~^ ERROR struct fields are separated by `,` +} + +fn main() {} diff --git a/src/test/ui/parser/recover-field-semi.stderr b/src/test/ui/parser/recover-field-semi.stderr new file mode 100644 index 00000000000..657366db9b4 --- /dev/null +++ b/src/test/ui/parser/recover-field-semi.stderr @@ -0,0 +1,29 @@ +error: struct fields are separated by `,` + --> $DIR/recover-field-semi.rs:2:13 + | +LL | foo: i32; + | ^ help: replace `;` with `,` + +error: union fields are separated by `,` + --> $DIR/recover-field-semi.rs:7:13 + | +LL | foo: i32; + | ^ help: replace `;` with `,` + +error: struct fields are separated by `,` + --> $DIR/recover-field-semi.rs:12:19 + | +LL | Qux { foo: i32; } + | ^ help: replace `;` with `,` + +error: unions cannot have zero fields + --> $DIR/recover-field-semi.rs:6:1 + | +LL | / union Bar { +LL | | foo: i32; +LL | | +LL | | } + | |_^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.rs b/src/test/ui/parser/removed-syntax-field-semicolon.rs index ac28e21ae03..808f2a5cc38 100644 --- a/src/test/ui/parser/removed-syntax-field-semicolon.rs +++ b/src/test/ui/parser/removed-syntax-field-semicolon.rs @@ -1,6 +1,6 @@ struct S { bar: (); - //~^ ERROR expected `,`, or `}`, found `;` + //~^ ERROR struct fields are separated by `,` } fn main() {} diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.stderr b/src/test/ui/parser/removed-syntax-field-semicolon.stderr index fbefeb26a50..e4f75f67206 100644 --- a/src/test/ui/parser/removed-syntax-field-semicolon.stderr +++ b/src/test/ui/parser/removed-syntax-field-semicolon.stderr @@ -1,8 +1,8 @@ -error: expected `,`, or `}`, found `;` +error: struct fields are separated by `,` --> $DIR/removed-syntax-field-semicolon.rs:2:12 | LL | bar: (); - | ^ + | ^ help: replace `;` with `,` error: aborting due to previous error diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed b/src/test/ui/parser/suggest-semicolon-before-array.fixed index a06b58b2740..a06b58b2740 100644 --- a/src/test/ui/parser/suggest-suggest-semicolon-before-array.fixed +++ b/src/test/ui/parser/suggest-semicolon-before-array.fixed diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.rs b/src/test/ui/parser/suggest-semicolon-before-array.rs index f601ca2aef5..f601ca2aef5 100644 --- a/src/test/ui/parser/suggest-suggest-semicolon-before-array.rs +++ b/src/test/ui/parser/suggest-semicolon-before-array.rs diff --git a/src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr b/src/test/ui/parser/suggest-semicolon-before-array.stderr index bf86b43554d..8a33321fbd5 100644 --- a/src/test/ui/parser/suggest-suggest-semicolon-before-array.stderr +++ b/src/test/ui/parser/suggest-semicolon-before-array.stderr @@ -1,5 +1,5 @@ error: expected `;`, found `[` - --> $DIR/suggest-suggest-semicolon-before-array.rs:8:5 + --> $DIR/suggest-semicolon-before-array.rs:8:5 | LL | [1, 3] | ^ diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs index d968c48fb1a..5d4181a30f0 100644 --- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -22,22 +22,22 @@ fn main() { HiddenEnum::A => {} HiddenEnum::C => {} } - //~^^^^ non-exhaustive patterns: `B` not covered + //~^^^^ non-exhaustive patterns: `HiddenEnum::B` not covered match HiddenEnum::A { HiddenEnum::A => {} } - //~^^^ non-exhaustive patterns: `B` and `_` not covered + //~^^^ non-exhaustive patterns: `HiddenEnum::B` and `_` not covered match None { None => {} Some(HiddenEnum::A) => {} } - //~^^^^ non-exhaustive patterns: `Some(B)` and `Some(_)` not covered + //~^^^^ non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered match InCrate::A { InCrate::A => {} InCrate::B => {} } - //~^^^^ non-exhaustive patterns: `C` not covered + //~^^^^ non-exhaustive patterns: `InCrate::C` not covered } diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index 643e734f9d4..b450a9aeddf 100644 --- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -16,11 +16,11 @@ LL ~ HiddenEnum::B => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `B` not covered +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` not covered --> $DIR/doc-hidden-non-exhaustive.rs:21:11 | LL | match HiddenEnum::A { - | ^^^^^^^^^^^^^ pattern `B` not covered + | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered | note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 @@ -34,14 +34,14 @@ LL | B, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ HiddenEnum::C => {} -LL + B => todo!() +LL + HiddenEnum::B => todo!() | -error[E0004]: non-exhaustive patterns: `B` and `_` not covered +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` and `_` not covered --> $DIR/doc-hidden-non-exhaustive.rs:27:11 | LL | match HiddenEnum::A { - | ^^^^^^^^^^^^^ patterns `B` and `_` not covered + | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered | note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 @@ -55,14 +55,14 @@ LL | B, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ HiddenEnum::A => {} -LL + B | _ => todo!() +LL + HiddenEnum::B | _ => todo!() | -error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered +error[E0004]: non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered --> $DIR/doc-hidden-non-exhaustive.rs:32:11 | LL | match None { - | ^^^^ patterns `Some(B)` and `Some(_)` not covered + | ^^^^ patterns `Some(HiddenEnum::B)` and `Some(_)` not covered | note: `Option<HiddenEnum>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL @@ -76,14 +76,14 @@ LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ Some(HiddenEnum::A) => {} -LL + Some(B) | Some(_) => todo!() +LL + Some(HiddenEnum::B) | Some(_) => todo!() | -error[E0004]: non-exhaustive patterns: `C` not covered +error[E0004]: non-exhaustive patterns: `InCrate::C` not covered --> $DIR/doc-hidden-non-exhaustive.rs:38:11 | LL | match InCrate::A { - | ^^^^^^^^^^ pattern `C` not covered + | ^^^^^^^^^^ pattern `InCrate::C` not covered | note: `InCrate` defined here --> $DIR/doc-hidden-non-exhaustive.rs:11:5 @@ -97,7 +97,7 @@ LL | C, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ InCrate::B => {} -LL + C => todo!() +LL + InCrate::C => todo!() | error: aborting due to 5 previous errors diff --git a/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index d31ee0dbd14..5e12bc1d22f 100644 --- a/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -105,11 +105,11 @@ LL | union NonEmptyUnion2 { = note: the matched value is of type `NonEmptyUnion2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: `Foo(_)` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered --> $DIR/empty-match.rs:83:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here --> $DIR/empty-match.rs:24:5 @@ -121,11 +121,11 @@ LL | Foo(bool), = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern -error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered --> $DIR/empty-match.rs:84:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here --> $DIR/empty-match.rs:27:5 @@ -139,11 +139,11 @@ LL | Bar, = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:85:20 | LL | match_no_arms!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:30:6 @@ -238,11 +238,11 @@ LL ~ _ if false => {} LL + NonEmptyUnion2 { .. } => todo!() | -error[E0004]: non-exhaustive patterns: `Foo(_)` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered --> $DIR/empty-match.rs:92:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here --> $DIR/empty-match.rs:24:5 @@ -255,14 +255,14 @@ LL | Foo(bool), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {} -LL + Foo(_) => todo!() +LL + NonEmptyEnum1::Foo(_) => todo!() | -error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered --> $DIR/empty-match.rs:93:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here --> $DIR/empty-match.rs:27:5 @@ -277,14 +277,14 @@ LL | Bar, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ _ if false => {} -LL + Foo(_) | Bar => todo!() +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | -error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:94:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:30:6 diff --git a/src/test/ui/pattern/usefulness/empty-match.normal.stderr b/src/test/ui/pattern/usefulness/empty-match.normal.stderr index d31ee0dbd14..5e12bc1d22f 100644 --- a/src/test/ui/pattern/usefulness/empty-match.normal.stderr +++ b/src/test/ui/pattern/usefulness/empty-match.normal.stderr @@ -105,11 +105,11 @@ LL | union NonEmptyUnion2 { = note: the matched value is of type `NonEmptyUnion2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: `Foo(_)` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered --> $DIR/empty-match.rs:83:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here --> $DIR/empty-match.rs:24:5 @@ -121,11 +121,11 @@ LL | Foo(bool), = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern -error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered --> $DIR/empty-match.rs:84:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here --> $DIR/empty-match.rs:27:5 @@ -139,11 +139,11 @@ LL | Bar, = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:85:20 | LL | match_no_arms!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:30:6 @@ -238,11 +238,11 @@ LL ~ _ if false => {} LL + NonEmptyUnion2 { .. } => todo!() | -error[E0004]: non-exhaustive patterns: `Foo(_)` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered --> $DIR/empty-match.rs:92:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here --> $DIR/empty-match.rs:24:5 @@ -255,14 +255,14 @@ LL | Foo(bool), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {} -LL + Foo(_) => todo!() +LL + NonEmptyEnum1::Foo(_) => todo!() | -error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered --> $DIR/empty-match.rs:93:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here --> $DIR/empty-match.rs:27:5 @@ -277,14 +277,14 @@ LL | Bar, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ _ if false => {} -LL + Foo(_) | Bar => todo!() +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | -error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:94:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:30:6 diff --git a/src/test/ui/pattern/usefulness/empty-match.rs b/src/test/ui/pattern/usefulness/empty-match.rs index 8110ec013d7..9cdc0413ba1 100644 --- a/src/test/ui/pattern/usefulness/empty-match.rs +++ b/src/test/ui/pattern/usefulness/empty-match.rs @@ -80,16 +80,16 @@ fn main() { match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty - match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered - match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered - match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered + match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered match_guarded_arm!(0u8); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered - match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered - match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered - match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered + match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered } diff --git a/src/test/ui/pattern/usefulness/issue-15129.rs b/src/test/ui/pattern/usefulness/issue-15129.rs index d2b72a86b74..f02e5c0c6f8 100644 --- a/src/test/ui/pattern/usefulness/issue-15129.rs +++ b/src/test/ui/pattern/usefulness/issue-15129.rs @@ -10,7 +10,7 @@ pub enum V { fn main() { match (T::T1(()), V::V2(true)) { - //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered + //~^ ERROR non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered (T::T1(()), V::V1(i)) => (), (T::T2(()), V::V2(b)) => (), } diff --git a/src/test/ui/pattern/usefulness/issue-15129.stderr b/src/test/ui/pattern/usefulness/issue-15129.stderr index af60f3ff50b..ee8410b7650 100644 --- a/src/test/ui/pattern/usefulness/issue-15129.stderr +++ b/src/test/ui/pattern/usefulness/issue-15129.stderr @@ -1,14 +1,14 @@ -error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered +error[E0004]: non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered --> $DIR/issue-15129.rs:12:11 | LL | match (T::T1(()), V::V2(true)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered | = note: the matched value is of type `(T, V)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ (T::T2(()), V::V2(b)) => (), -LL ~ (T1(()), V2(_)) | (T2(()), V1(_)) => todo!(), +LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(), | error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/issue-31561.rs b/src/test/ui/pattern/usefulness/issue-31561.rs index 813b2409cc8..5b878851a31 100644 --- a/src/test/ui/pattern/usefulness/issue-31561.rs +++ b/src/test/ui/pattern/usefulness/issue-31561.rs @@ -6,5 +6,5 @@ enum Thing { fn main() { let Thing::Foo(y) = Thing::Foo(1); - //~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered + //~^ ERROR refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered } diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr index 9da6b5eeead..46aebccc5ff 100644 --- a/src/test/ui/pattern/usefulness/issue-31561.stderr +++ b/src/test/ui/pattern/usefulness/issue-31561.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered +error[E0005]: refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered --> $DIR/issue-31561.rs:8:9 | LL | let Thing::Foo(y) = Thing::Foo(1); - | ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered + | ^^^^^^^^^^^^^ patterns `Thing::Bar` and `Thing::Baz` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/pattern/usefulness/issue-35609.stderr b/src/test/ui/pattern/usefulness/issue-35609.stderr index 2247b818d43..c9781d52e6d 100644 --- a/src/test/ui/pattern/usefulness/issue-35609.stderr +++ b/src/test/ui/pattern/usefulness/issue-35609.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered --> $DIR/issue-35609.rs:10:11 | LL | match (A, ()) { - | ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered + | ^^^^^^^ patterns `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered | = note: the matched value is of type `(Enum, ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms @@ -11,11 +11,11 @@ LL ~ (A, _) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered --> $DIR/issue-35609.rs:14:11 | LL | match (A, A) { - | ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered + | ^^^^^^ patterns `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered | = note: the matched value is of type `(Enum, Enum)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms @@ -24,11 +24,11 @@ LL ~ (_, A) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered --> $DIR/issue-35609.rs:18:11 | LL | match ((A, ()), ()) { - | ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered | = note: the matched value is of type `((Enum, ()), ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms @@ -37,11 +37,11 @@ LL ~ ((A, ()), _) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered --> $DIR/issue-35609.rs:22:11 | LL | match ((A, ()), A) { - | ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered + | ^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered | = note: the matched value is of type `((Enum, ()), Enum)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms @@ -50,11 +50,11 @@ LL ~ ((A, ()), _) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered --> $DIR/issue-35609.rs:26:11 | LL | match ((A, ()), ()) { - | ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered | = note: the matched value is of type `((Enum, ()), ())` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms @@ -63,11 +63,11 @@ LL ~ ((A, _), _) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered --> $DIR/issue-35609.rs:31:11 | LL | match S(A, ()) { - | ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered + | ^^^^^^^^ patterns `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered | note: `S` defined here --> $DIR/issue-35609.rs:6:8 @@ -81,11 +81,11 @@ LL ~ S(A, _) => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered +error[E0004]: non-exhaustive patterns: `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered --> $DIR/issue-35609.rs:35:11 | LL | match (Sd { x: A, y: () }) { - | ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered + | ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered | note: `Sd` defined here --> $DIR/issue-35609.rs:7:8 @@ -99,11 +99,11 @@ LL ~ Sd { x: A, y: _ } => {} LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered +error[E0004]: non-exhaustive patterns: `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered --> $DIR/issue-35609.rs:39:11 | LL | match Some(A) { - | ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered + | ^^^^^^^ patterns `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered | note: `Option<Enum>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/src/test/ui/pattern/usefulness/issue-39362.stderr b/src/test/ui/pattern/usefulness/issue-39362.stderr index ca37af6fb80..b8b17918aef 100644 --- a/src/test/ui/pattern/usefulness/issue-39362.stderr +++ b/src/test/ui/pattern/usefulness/issue-39362.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered +error[E0004]: non-exhaustive patterns: `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered --> $DIR/issue-39362.rs:10:11 | LL | match f { - | ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered + | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered | note: `Foo` defined here --> $DIR/issue-39362.rs:2:5 diff --git a/src/test/ui/pattern/usefulness/issue-40221.stderr b/src/test/ui/pattern/usefulness/issue-40221.stderr index c477e435335..4973e42b054 100644 --- a/src/test/ui/pattern/usefulness/issue-40221.stderr +++ b/src/test/ui/pattern/usefulness/issue-40221.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `C(QA)` not covered +error[E0004]: non-exhaustive patterns: `P::C(PC::QA)` not covered --> $DIR/issue-40221.rs:11:11 | LL | match proto { - | ^^^^^ pattern `C(QA)` not covered + | ^^^^^ pattern `P::C(PC::QA)` not covered | note: `P` defined here --> $DIR/issue-40221.rs:2:5 @@ -15,7 +15,7 @@ LL | C(PC), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ P::C(PC::Q) => (), -LL ~ C(QA) => todo!(), +LL ~ P::C(PC::QA) => todo!(), | error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/issue-50900.rs b/src/test/ui/pattern/usefulness/issue-50900.rs index 27135af9575..9cc760e9a10 100644 --- a/src/test/ui/pattern/usefulness/issue-50900.rs +++ b/src/test/ui/pattern/usefulness/issue-50900.rs @@ -13,7 +13,7 @@ impl Tag { fn main() { match Tag::ExifIFDPointer { - //~^ ERROR: non-exhaustive patterns: `Tag(Exif, _)` not covered + //~^ ERROR: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered Tag::ExifIFDPointer => {} } } diff --git a/src/test/ui/pattern/usefulness/issue-50900.stderr b/src/test/ui/pattern/usefulness/issue-50900.stderr index 2bdbecabbbe..348246d28aa 100644 --- a/src/test/ui/pattern/usefulness/issue-50900.stderr +++ b/src/test/ui/pattern/usefulness/issue-50900.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Tag(Exif, _)` not covered +error[E0004]: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered --> $DIR/issue-50900.rs:15:11 | LL | match Tag::ExifIFDPointer { - | ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Exif, _)` not covered + | ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Context::Exif, _)` not covered | note: `Tag` defined here --> $DIR/issue-50900.rs:2:12 @@ -13,7 +13,7 @@ LL | pub struct Tag(pub Context, pub u16); help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Tag::ExifIFDPointer => {} -LL + Tag(Exif, _) => todo!() +LL + Tag(Context::Exif, _) => todo!() | error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/issue-56379.rs b/src/test/ui/pattern/usefulness/issue-56379.rs index 9bccccca9c2..097cf98d012 100644 --- a/src/test/ui/pattern/usefulness/issue-56379.rs +++ b/src/test/ui/pattern/usefulness/issue-56379.rs @@ -6,7 +6,7 @@ enum Foo { fn main() { match Foo::A(true) { - //~^ ERROR non-exhaustive patterns: `A(false)`, `B(false)` and `C(false)` not covered + //~^ ERROR non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered Foo::A(true) => {} Foo::B(true) => {} Foo::C(true) => {} diff --git a/src/test/ui/pattern/usefulness/issue-56379.stderr b/src/test/ui/pattern/usefulness/issue-56379.stderr index f6261001c5e..6eed6bfae4c 100644 --- a/src/test/ui/pattern/usefulness/issue-56379.stderr +++ b/src/test/ui/pattern/usefulness/issue-56379.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `A(false)`, `B(false)` and `C(false)` not covered +error[E0004]: non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered --> $DIR/issue-56379.rs:8:11 | LL | match Foo::A(true) { - | ^^^^^^^^^^^^ patterns `A(false)`, `B(false)` and `C(false)` not covered + | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered | note: `Foo` defined here --> $DIR/issue-56379.rs:2:5 @@ -19,7 +19,7 @@ LL | C(bool), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ Foo::C(true) => {} -LL + A(false) | B(false) | C(false) => todo!() +LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!() | error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/issue-72377.rs b/src/test/ui/pattern/usefulness/issue-72377.rs index b0d8a53ed93..b5ad3075ca7 100644 --- a/src/test/ui/pattern/usefulness/issue-72377.rs +++ b/src/test/ui/pattern/usefulness/issue-72377.rs @@ -6,7 +6,7 @@ fn main() { let y = Some(X::A); match (x, y) { - //~^ ERROR non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 + //~^ ERROR non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 //~| more not covered (_, None) => false, (v, Some(w)) if v == w => true, diff --git a/src/test/ui/pattern/usefulness/issue-72377.stderr b/src/test/ui/pattern/usefulness/issue-72377.stderr index 20f002dd3db..123dd051d24 100644 --- a/src/test/ui/pattern/usefulness/issue-72377.stderr +++ b/src/test/ui/pattern/usefulness/issue-72377.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered +error[E0004]: non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered --> $DIR/issue-72377.rs:8:11 | LL | match (x, y) { - | ^^^^^^ patterns `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered + | ^^^^^^ patterns `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered | = note: the matched value is of type `(X, Option<X>)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.rs b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs index 4c5f2d35649..3c9c16561c0 100644 --- a/src/test/ui/pattern/usefulness/match-arm-statics-2.rs +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs @@ -27,7 +27,7 @@ const EAST: Direction = East; fn nonexhaustive_2() { match Some(Some(North)) { - //~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered + //~^ ERROR non-exhaustive patterns: `Some(Some(Direction::West))` not covered Some(NONE) => (), Some(Some(North)) => (), Some(Some(EAST)) => (), @@ -46,7 +46,7 @@ const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE }; fn nonexhaustive_3() { match (Foo { bar: Some(North), baz: NewBool(true) }) { - //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` + //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` Foo { bar: None, baz: NewBool(true) } => (), Foo { bar: _, baz: NEW_FALSE } => (), Foo { bar: Some(West), baz: NewBool(true) } => (), diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr index a2b66f5ed67..b0d7fe5eb68 100644 --- a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -11,11 +11,11 @@ LL ~ (false, true) => (), LL + (true, false) => todo!() | -error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered +error[E0004]: non-exhaustive patterns: `Some(Some(Direction::West))` not covered --> $DIR/match-arm-statics-2.rs:29:11 | LL | match Some(Some(North)) { - | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered + | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(Direction::West))` not covered | note: `Option<Option<Direction>>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL @@ -32,14 +32,14 @@ LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => (), -LL + Some(Some(West)) => todo!() +LL + Some(Some(Direction::West)) => todo!() | -error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered +error[E0004]: non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered --> $DIR/match-arm-statics-2.rs:48:11 | LL | match (Foo { bar: Some(North), baz: NewBool(true) }) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered | note: `Foo` defined here --> $DIR/match-arm-statics-2.rs:40:8 @@ -50,7 +50,7 @@ LL | struct Foo { help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo { bar: Some(EAST), .. } => (), -LL + Foo { bar: Some(North), baz: NewBool(true) } => todo!() +LL + Foo { bar: Some(Direction::North), baz: NewBool(true) } => todo!() | error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs index 2e15bc2d2a5..af42fc1aeb4 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -35,43 +35,43 @@ enum E { fn by_val(e: E) { let e1 = e.clone(); - match e1 { //~ ERROR non-exhaustive patterns: `B` and `C` not covered - //~^ NOTE patterns `B` and `C` not covered + match e1 { //~ ERROR non-exhaustive patterns: `E::B` and `E::C` not covered + //~^ NOTE patterns `E::B` and `E::C` not covered //~| NOTE the matched value is of type `E` E::A => {} } - let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered - //~^ NOTE patterns `B` and `C` not covered + let E::A = e; //~ ERROR refutable pattern in local binding: `E::B` and `E::C` not covered + //~^ NOTE patterns `E::B` and `E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE the matched value is of type `E` } fn by_ref_once(e: &E) { - match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered - //~^ NOTE patterns `&B` and `&C` not covered + match e { //~ ERROR non-exhaustive patterns: `&E::B` and `&E::C` not covered + //~^ NOTE patterns `&E::B` and `&E::C` not covered //~| NOTE the matched value is of type `&E` E::A => {} } - let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered - //~^ NOTE patterns `&B` and `&C` not covered + let E::A = e; //~ ERROR refutable pattern in local binding: `&E::B` and `&E::C` not covered + //~^ NOTE patterns `&E::B` and `&E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE the matched value is of type `&E` } fn by_ref_thrice(e: & &mut &E) { - match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered - //~^ NOTE patterns `&&mut &B` and `&&mut &C` not covered + match e { //~ ERROR non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered + //~^ NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| NOTE the matched value is of type `&&mut &E` E::A => {} } let E::A = e; - //~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered - //~| NOTE patterns `&&mut &B` and `&&mut &C` not covered + //~^ ERROR refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html //~| NOTE the matched value is of type `&&mut &E` @@ -89,15 +89,15 @@ enum Opt { } fn ref_pat(e: Opt) { - match e {//~ ERROR non-exhaustive patterns: `None` not covered - //~^ NOTE pattern `None` not covered + match e {//~ ERROR non-exhaustive patterns: `Opt::None` not covered + //~^ NOTE pattern `Opt::None` not covered //~| NOTE the matched value is of type `Opt` Opt::Some(ref _x) => {} } - let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered + let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `Opt::None` not covered //~^ NOTE the matched value is of type `Opt` - //~| NOTE pattern `None` not covered + //~| NOTE pattern `Opt::None` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html } diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 0f06c31c468..ac2a9713e7d 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `B` and `C` not covered +error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:38:11 | LL | match e1 { - | ^^ patterns `B` and `C` not covered + | ^^ patterns `E::B` and `E::C` not covered | note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:14:5 @@ -19,14 +19,14 @@ LL | C help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ E::A => {} -LL + B | C => todo!() +LL + E::B | E::C => todo!() | -error[E0005]: refutable pattern in local binding: `B` and `C` not covered +error[E0005]: refutable pattern in local binding: `E::B` and `E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:44:9 | LL | let E::A = e; - | ^^^^ patterns `B` and `C` not covered + | ^^^^ patterns `E::B` and `E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html @@ -47,11 +47,11 @@ help: you might want to use `if let` to ignore the variants that aren't matched LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered +error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:52:11 | LL | match e { - | ^ patterns `&B` and `&C` not covered + | ^ patterns `&E::B` and `&E::C` not covered | note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:14:5 @@ -68,14 +68,14 @@ LL | C help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ E::A => {} -LL + &B | &C => todo!() +LL + &E::B | &E::C => todo!() | -error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered +error[E0005]: refutable pattern in local binding: `&E::B` and `&E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:58:9 | LL | let E::A = e; - | ^^^^ patterns `&B` and `&C` not covered + | ^^^^ patterns `&E::B` and `&E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html @@ -96,11 +96,11 @@ help: you might want to use `if let` to ignore the variants that aren't matched LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered +error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:66:11 | LL | match e { - | ^ patterns `&&mut &B` and `&&mut &C` not covered + | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | note: `E` defined here --> $DIR/non-exhaustive-defined-here.rs:14:5 @@ -117,14 +117,14 @@ LL | C help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ E::A => {} -LL + &&mut &B | &&mut &C => todo!() +LL + &&mut &E::B | &&mut &E::C => todo!() | -error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered +error[E0005]: refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered --> $DIR/non-exhaustive-defined-here.rs:72:9 | LL | let E::A = e; - | ^^^^ patterns `&&mut &B` and `&&mut &C` not covered + | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html @@ -145,11 +145,11 @@ help: you might want to use `if let` to ignore the variants that aren't matched LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -error[E0004]: non-exhaustive patterns: `None` not covered +error[E0004]: non-exhaustive patterns: `Opt::None` not covered --> $DIR/non-exhaustive-defined-here.rs:92:11 | LL | match e { - | ^ pattern `None` not covered + | ^ pattern `Opt::None` not covered | note: `Opt` defined here --> $DIR/non-exhaustive-defined-here.rs:84:5 @@ -163,14 +163,14 @@ LL | None, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Opt::Some(ref _x) => {} -LL + None => todo!() +LL + Opt::None => todo!() | -error[E0005]: refutable pattern in local binding: `None` not covered +error[E0005]: refutable pattern in local binding: `Opt::None` not covered --> $DIR/non-exhaustive-defined-here.rs:98:9 | LL | let Opt::Some(ref _x) = e; - | ^^^^^^^^^^^^^^^^^ pattern `None` not covered + | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs index d198144790b..69c3c76580a 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs @@ -12,7 +12,7 @@ fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'s fn main() { let x = T::A(U::C); - match x { //~ ERROR non-exhaustive patterns: `A(C)` not covered + match x { //~ ERROR non-exhaustive patterns: `T::A(U::C)` not covered T::A(U::D) => { panic!("hello"); } T::B => { panic!("goodbye"); } } diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr index cbbd544f943..44f32742110 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -11,11 +11,11 @@ LL ~ (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)", LL + (Some(&[]), Err(_)) => todo!() | -error[E0004]: non-exhaustive patterns: `A(C)` not covered +error[E0004]: non-exhaustive patterns: `T::A(U::C)` not covered --> $DIR/non-exhaustive-match-nested.rs:15:11 | LL | match x { - | ^ pattern `A(C)` not covered + | ^ pattern `T::A(U::C)` not covered | note: `T` defined here --> $DIR/non-exhaustive-match-nested.rs:1:10 @@ -26,7 +26,7 @@ LL | enum T { A(U), B } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ T::B => { panic!("goodbye"); } -LL + A(C) => todo!() +LL + T::A(U::C) => todo!() | error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs index 4ff12aa2ff5..1cb58b8cebe 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs @@ -4,7 +4,7 @@ enum T { A, B } fn main() { let x = T::A; - match x { T::B => { } } //~ ERROR non-exhaustive patterns: `A` not covered + match x { T::B => { } } //~ ERROR non-exhaustive patterns: `T::A` not covered match true { //~ ERROR non-exhaustive patterns: `false` not covered true => {} } @@ -15,11 +15,11 @@ fn main() { // and `(_, _, 5_i32..=i32::MAX)` not covered (_, _, 4) => {} } - match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` and `(B, B)` not covered + match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered (T::A, T::B) => {} (T::B, T::A) => {} } - match T::A { //~ ERROR non-exhaustive patterns: `B` not covered + match T::A { //~ ERROR non-exhaustive patterns: `T::B` not covered T::A => {} } // This is exhaustive, though the algorithm got it wrong at one point diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr index f2362c316df..4234600d0d0 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `A` not covered +error[E0004]: non-exhaustive patterns: `T::A` not covered --> $DIR/non-exhaustive-match.rs:7:11 | LL | match x { T::B => { } } - | ^ pattern `A` not covered + | ^ pattern `T::A` not covered | note: `T` defined here --> $DIR/non-exhaustive-match.rs:3:10 @@ -12,8 +12,8 @@ LL | enum T { A, B } = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match x { T::B => { }, A => todo!() } - | ++++++++++++++ +LL | match x { T::B => { }, T::A => todo!() } + | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `false` not covered --> $DIR/non-exhaustive-match.rs:8:11 @@ -62,24 +62,24 @@ LL ~ (_, _, 4) => {} LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() | -error[E0004]: non-exhaustive patterns: `(A, A)` and `(B, B)` not covered +error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered --> $DIR/non-exhaustive-match.rs:18:11 | LL | match (T::A, T::A) { - | ^^^^^^^^^^^^ patterns `(A, A)` and `(B, B)` not covered + | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered | = note: the matched value is of type `(T, T)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ (T::B, T::A) => {} -LL + (A, A) | (B, B) => todo!() +LL + (T::A, T::A) | (T::B, T::B) => todo!() | -error[E0004]: non-exhaustive patterns: `B` not covered +error[E0004]: non-exhaustive patterns: `T::B` not covered --> $DIR/non-exhaustive-match.rs:22:11 | LL | match T::A { - | ^^^^ pattern `B` not covered + | ^^^^ pattern `T::B` not covered | note: `T` defined here --> $DIR/non-exhaustive-match.rs:3:13 @@ -90,7 +90,7 @@ LL | enum T { A, B } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ T::A => {} -LL + B => todo!() +LL + T::B => todo!() | error[E0004]: non-exhaustive patterns: `[]` not covered diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs index abb4ea8daf5..4bd34421922 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs @@ -21,7 +21,7 @@ enum Color { fn enum_with_single_missing_variant() { match Color::Red { - //~^ ERROR non-exhaustive patterns: `Red` not covered + //~^ ERROR non-exhaustive patterns: `Color::Red` not covered Color::CustomRGBA { .. } => (), Color::Green => () } @@ -33,7 +33,7 @@ enum Direction { fn enum_with_multiple_missing_variants() { match Direction::North { - //~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered + //~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered Direction::North => () } } @@ -44,7 +44,7 @@ enum ExcessiveEnum { fn enum_with_excessive_missing_variants() { match ExcessiveEnum::First { - //~^ ERROR `Second`, `Third`, `Fourth` and 8 more not covered + //~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered ExcessiveEnum::First => () } @@ -52,7 +52,7 @@ fn enum_with_excessive_missing_variants() { fn enum_struct_variant() { match Color::Red { - //~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered + //~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered Color::Red => (), Color::Green => (), Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (), @@ -68,7 +68,7 @@ enum Enum { fn vectors_with_nested_enums() { let x: &'static [Enum] = &[Enum::First, Enum::Second(false)]; match *x { - //~^ ERROR non-exhaustive patterns: `[Second(true), Second(false)]` not covered + //~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered [] => (), [_] => (), [Enum::First, _] => (), diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index b0cfd631fb0..b8af566de7c 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -16,11 +16,11 @@ LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (), LL + Foo { first: false, second: Some([_, _, _, _]) } => todo!() | -error[E0004]: non-exhaustive patterns: `Red` not covered +error[E0004]: non-exhaustive patterns: `Color::Red` not covered --> $DIR/non-exhaustive-pattern-witness.rs:23:11 | LL | match Color::Red { - | ^^^^^^^^^^ pattern `Red` not covered + | ^^^^^^^^^^ pattern `Color::Red` not covered | note: `Color` defined here --> $DIR/non-exhaustive-pattern-witness.rs:17:5 @@ -33,14 +33,14 @@ LL | Red, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Color::Green => (), -LL + Red => todo!() +LL + Color::Red => todo!() | -error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered +error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered --> $DIR/non-exhaustive-pattern-witness.rs:35:11 | LL | match Direction::North { - | ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered + | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered | note: `Direction` defined here --> $DIR/non-exhaustive-pattern-witness.rs:31:12 @@ -56,14 +56,14 @@ LL | North, East, South, West help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ Direction::North => (), -LL + East | South | West => todo!() +LL + Direction::East | Direction::South | Direction::West => todo!() | -error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered +error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered --> $DIR/non-exhaustive-pattern-witness.rs:46:11 | LL | match ExcessiveEnum::First { - | ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered + | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered | note: `ExcessiveEnum` defined here --> $DIR/non-exhaustive-pattern-witness.rs:41:6 @@ -77,11 +77,11 @@ LL ~ ExcessiveEnum::First => (), LL + _ => todo!() | -error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered +error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered --> $DIR/non-exhaustive-pattern-witness.rs:54:11 | LL | match Color::Red { - | ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered + | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered | note: `Color` defined here --> $DIR/non-exhaustive-pattern-witness.rs:19:5 @@ -95,20 +95,20 @@ LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (), -LL + CustomRGBA { a: true, .. } => todo!() +LL + Color::CustomRGBA { a: true, .. } => todo!() | -error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered +error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered --> $DIR/non-exhaustive-pattern-witness.rs:70:11 | LL | match *x { - | ^^ pattern `[Second(true), Second(false)]` not covered + | ^^ pattern `[Enum::Second(true), Enum::Second(false)]` not covered | = note: the matched value is of type `[Enum]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ [_, _, ref tail @ .., _] => (), -LL + [Second(true), Second(false)] => todo!() +LL + [Enum::Second(true), Enum::Second(false)] => todo!() | error[E0004]: non-exhaustive patterns: `((), false)` not covered diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs index ff1c472e24f..03db01160dd 100644 --- a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs @@ -8,7 +8,7 @@ fn main() { match UnstableEnum::Stable { UnstableEnum::Stable => {} } - //~^^^ non-exhaustive patterns: `Stable2` and `_` not covered + //~^^^ non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered match UnstableEnum::Stable { UnstableEnum::Stable => {} diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr index 98c75953add..7b8588a3c73 100644 --- a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered +error[E0004]: non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered --> $DIR/stable-gated-patterns.rs:8:11 | LL | match UnstableEnum::Stable { - | ^^^^^^^^^^^^^^^^^^^^ patterns `Stable2` and `_` not covered + | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered | note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:9:5 @@ -16,7 +16,7 @@ LL | Stable2, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ UnstableEnum::Stable => {} -LL + Stable2 | _ => todo!() +LL + UnstableEnum::Stable2 | _ => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered diff --git a/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr index 6127fad3f7d..85c97be29d6 100644 --- a/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr +++ b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered +error[E0004]: non-exhaustive patterns: `A::B { x: Some(_) }` not covered --> $DIR/struct-like-enum-nonexhaustive.rs:8:11 | LL | match x { - | ^ pattern `B { x: Some(_) }` not covered + | ^ pattern `A::B { x: Some(_) }` not covered | note: `A` defined here --> $DIR/struct-like-enum-nonexhaustive.rs:2:5 @@ -15,7 +15,7 @@ LL | B { x: Option<isize> }, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ A::B { x: None } => {} -LL + B { x: Some(_) } => todo!() +LL + A::B { x: Some(_) } => todo!() | error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs index bdab327fd57..7046555e0d2 100644 --- a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -11,7 +11,7 @@ fn main() { UnstableEnum::Stable => {} UnstableEnum::Stable2 => {} } - //~^^^^ non-exhaustive patterns: `Unstable` not covered + //~^^^^ non-exhaustive patterns: `UnstableEnum::Unstable` not covered // Ok: all variants are explicitly matched match UnstableEnum::Stable { diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr index f07a25ca89b..6dc9a405839 100644 --- a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Unstable` not covered +error[E0004]: non-exhaustive patterns: `UnstableEnum::Unstable` not covered --> $DIR/unstable-gated-patterns.rs:10:11 | LL | match UnstableEnum::Stable { - | ^^^^^^^^^^^^^^^^^^^^ pattern `Unstable` not covered + | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered | note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:11:5 @@ -16,7 +16,7 @@ LL | Unstable, help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ UnstableEnum::Stable2 => {} -LL + Unstable => todo!() +LL + UnstableEnum::Unstable => todo!() | error: aborting due to previous error diff --git a/src/test/ui/repr/invalid_repr_list_help.rs b/src/test/ui/repr/invalid_repr_list_help.rs new file mode 100644 index 00000000000..c320984536c --- /dev/null +++ b/src/test/ui/repr/invalid_repr_list_help.rs @@ -0,0 +1,17 @@ +#![crate_type = "lib"] + +#[repr(uwu)] //~ERROR: unrecognized representation hint +pub struct OwO; + +#[repr(uwu = "a")] //~ERROR: unrecognized representation hint +pub struct OwO2(i32); + +#[repr(uwu(4))] //~ERROR: unrecognized representation hint +pub struct OwO3 { + x: i32, +} + +#[repr(uwu, u8)] //~ERROR: unrecognized representation hint +pub enum OwO4 { + UwU = 1, +} diff --git a/src/test/ui/repr/invalid_repr_list_help.stderr b/src/test/ui/repr/invalid_repr_list_help.stderr new file mode 100644 index 00000000000..2acd56d9a32 --- /dev/null +++ b/src/test/ui/repr/invalid_repr_list_help.stderr @@ -0,0 +1,35 @@ +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:3:8 + | +LL | #[repr(uwu)] + | ^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:6:8 + | +LL | #[repr(uwu = "a")] + | ^^^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:9:8 + | +LL | #[repr(uwu(4))] + | ^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:14:8 + | +LL | #[repr(uwu, u8)] + | ^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0552`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs index 70253a4fc90..69a283c3163 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs @@ -31,7 +31,7 @@ fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) { fn main() { match NonExhaustiveEnum::Unit {} - //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004] + //~^ ERROR `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered [E0004] match NormalEnum::Unit {} - //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004] + //~^ ERROR `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered [E0004] } diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index 1f20904483f..de1bf8be885 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -10,11 +10,11 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered +error[E0004]: non-exhaustive patterns: `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered --> $DIR/enum_same_crate_empty_match.rs:33:11 | LL | match NonExhaustiveEnum::Unit {} - | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered | note: `NonExhaustiveEnum` defined here --> $DIR/enum_same_crate_empty_match.rs:5:5 @@ -33,15 +33,15 @@ LL | Struct { field: u32 } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ match NonExhaustiveEnum::Unit { -LL + Unit | Tuple(_) | Struct { .. } => todo!(), +LL + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_) | NonExhaustiveEnum::Struct { .. } => todo!(), LL + } | -error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered +error[E0004]: non-exhaustive patterns: `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered --> $DIR/enum_same_crate_empty_match.rs:35:11 | LL | match NormalEnum::Unit {} - | ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered + | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered | note: `NormalEnum` defined here --> $DIR/enum_same_crate_empty_match.rs:14:5 @@ -60,7 +60,7 @@ LL | Struct { field: u32 } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ match NormalEnum::Unit { -LL + Unit | Tuple(_) | Struct { .. } => todo!(), +LL + NormalEnum::Unit | NormalEnum::Tuple(_) | NormalEnum::Struct { .. } => todo!(), LL + } | diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr index a9885449f3f..4b9f8564d23 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -81,7 +81,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:58:9 | LL | _ => {} - | ^ pattern `Struct { .. }` not covered + | ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:57:16 @@ -95,7 +95,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:65:9 | LL | _ => {} - | ^ pattern `Tuple(_)` not covered + | ^ pattern `NonExhaustiveEnum::Tuple(_)` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:64:16 @@ -109,7 +109,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:75:9 | LL | _ => {} - | ^ pattern `Unit` not covered + | ^ pattern `NonExhaustiveEnum::Unit` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:74:16 @@ -123,7 +123,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:92:32 | LL | NestedNonExhaustive::A(_) => {} - | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | ^ patterns `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:89:12 @@ -137,7 +137,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:94:9 | LL | _ => {} - | ^ pattern `C` not covered + | ^ pattern `NestedNonExhaustive::C` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found @@ -146,7 +146,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:132:9 | LL | _ => {} - | ^ pattern `A(_)` not covered + | ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:130:12 @@ -160,7 +160,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:144:9 | LL | _ => {} - | ^ pattern `Unstable` not covered + | ^ pattern `UnstableEnum::Unstable` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:143:16 @@ -174,7 +174,7 @@ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:168:9 | LL | _ => {} - | ^ pattern `Unstable2` not covered + | ^ pattern `OnlyUnstableEnum::Unstable2` not covered | note: the lint level is defined here --> $DIR/omitted-patterns.rs:165:12 diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr index 7cce178988a..533e8abf2d6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -16,7 +16,7 @@ error: some variants are not matched explicitly --> $DIR/stable-omitted-patterns.rs:23:9 | LL | _ => {} - | ^ pattern `Stable2` not covered + | ^ pattern `UnstableEnum::Stable2` not covered | note: the lint level is defined here --> $DIR/stable-omitted-patterns.rs:22:16 diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 32a5c07f196..a9c54af0418 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -55,11 +55,11 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered --> $DIR/match.rs:31:11 | LL | match x {} - | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:17:23 @@ -74,7 +74,7 @@ LL | #[non_exhaustive] Struct { x: ! } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ match x { -LL + Tuple(_) | Struct { .. } => todo!(), +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), LL ~ } | diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr index c89c70ae6cc..ec2a2f6f055 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -36,11 +36,11 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered --> $DIR/match_same_crate.rs:38:11 | LL | match x {} - | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here --> $DIR/match_same_crate.rs:16:23 @@ -55,7 +55,7 @@ LL | #[non_exhaustive] Struct { x: ! } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ match x { -LL + Tuple(_) | Struct { .. } => todo!(), +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), LL ~ } | diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index d854ea28ff6..b6b777ec56c 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -55,11 +55,11 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered --> $DIR/match_with_exhaustive_patterns.rs:34:11 | LL | match x {} - | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:17:23 @@ -74,7 +74,7 @@ LL | #[non_exhaustive] Struct { x: ! } help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ match x { -LL + Tuple(_) | Struct { .. } => todo!(), +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), LL ~ } | diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs index a24b3ada57e..5102574d4be 100644 --- a/src/test/ui/stats/hir-stats.rs +++ b/src/test/ui/stats/hir-stats.rs @@ -1,6 +1,7 @@ // check-pass // compile-flags: -Zhir-stats // only-x86_64 +// ignore-stage1 // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 0a736f7be83..c8ceb6ff22d 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -21,39 +21,39 @@ ast-stats-1 - MacCall 32 ( 0.4%) 1 ast-stats-1 - Expr 96 ( 1.1%) 3 ast-stats-1 Param 160 ( 1.9%) 4 40 ast-stats-1 FnDecl 200 ( 2.4%) 5 40 -ast-stats-1 Variant 240 ( 2.8%) 2 120 +ast-stats-1 Variant 240 ( 2.9%) 2 120 ast-stats-1 Block 288 ( 3.4%) 6 48 ast-stats-1 GenericBound 352 ( 4.2%) 4 88 ast-stats-1 - Trait 352 ( 4.2%) 4 ast-stats-1 AssocItem 416 ( 4.9%) 4 104 ast-stats-1 - TyAlias 208 ( 2.5%) 2 ast-stats-1 - Fn 208 ( 2.5%) 2 -ast-stats-1 GenericParam 520 ( 6.1%) 5 104 -ast-stats-1 PathSegment 720 ( 8.5%) 30 24 -ast-stats-1 Expr 832 ( 9.8%) 8 104 +ast-stats-1 GenericParam 480 ( 5.7%) 5 96 +ast-stats-1 PathSegment 720 ( 8.6%) 30 24 +ast-stats-1 Expr 832 ( 9.9%) 8 104 ast-stats-1 - Path 104 ( 1.2%) 1 ast-stats-1 - Match 104 ( 1.2%) 1 ast-stats-1 - Struct 104 ( 1.2%) 1 ast-stats-1 - Lit 208 ( 2.5%) 2 ast-stats-1 - Block 312 ( 3.7%) 3 -ast-stats-1 Pat 840 ( 9.9%) 7 120 +ast-stats-1 Pat 840 (10.0%) 7 120 ast-stats-1 - Struct 120 ( 1.4%) 1 ast-stats-1 - Wild 120 ( 1.4%) 1 ast-stats-1 - Ident 600 ( 7.1%) 5 -ast-stats-1 Ty 1_344 (15.9%) 14 96 +ast-stats-1 Ty 1_344 (16.0%) 14 96 ast-stats-1 - Rptr 96 ( 1.1%) 1 ast-stats-1 - Ptr 96 ( 1.1%) 1 ast-stats-1 - ImplicitSelf 192 ( 2.3%) 2 ast-stats-1 - Path 960 (11.4%) 10 -ast-stats-1 Item 1_656 (19.6%) 9 184 +ast-stats-1 Item 1_656 (19.7%) 9 184 ast-stats-1 - Trait 184 ( 2.2%) 1 ast-stats-1 - Enum 184 ( 2.2%) 1 ast-stats-1 - ForeignMod 184 ( 2.2%) 1 ast-stats-1 - Impl 184 ( 2.2%) 1 ast-stats-1 - Fn 368 ( 4.4%) 2 -ast-stats-1 - Use 552 ( 6.5%) 3 +ast-stats-1 - Use 552 ( 6.6%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 8_456 +ast-stats-1 Total 8_416 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -86,12 +86,12 @@ ast-stats-2 - Trait 352 ( 3.8%) 4 ast-stats-2 AssocItem 416 ( 4.5%) 4 104 ast-stats-2 - TyAlias 208 ( 2.3%) 2 ast-stats-2 - Fn 208 ( 2.3%) 2 -ast-stats-2 GenericParam 520 ( 5.7%) 5 104 -ast-stats-2 PathSegment 792 ( 8.6%) 33 24 -ast-stats-2 Pat 840 ( 9.1%) 7 120 +ast-stats-2 GenericParam 480 ( 5.2%) 5 96 +ast-stats-2 PathSegment 792 ( 8.7%) 33 24 +ast-stats-2 Pat 840 ( 9.2%) 7 120 ast-stats-2 - Struct 120 ( 1.3%) 1 ast-stats-2 - Wild 120 ( 1.3%) 1 -ast-stats-2 - Ident 600 ( 6.5%) 5 +ast-stats-2 - Ident 600 ( 6.6%) 5 ast-stats-2 Expr 936 (10.2%) 9 104 ast-stats-2 - Path 104 ( 1.1%) 1 ast-stats-2 - Match 104 ( 1.1%) 1 @@ -99,12 +99,12 @@ ast-stats-2 - Struct 104 ( 1.1%) 1 ast-stats-2 - InlineAsm 104 ( 1.1%) 1 ast-stats-2 - Lit 208 ( 2.3%) 2 ast-stats-2 - Block 312 ( 3.4%) 3 -ast-stats-2 Ty 1_344 (14.6%) 14 96 +ast-stats-2 Ty 1_344 (14.7%) 14 96 ast-stats-2 - Rptr 96 ( 1.0%) 1 ast-stats-2 - Ptr 96 ( 1.0%) 1 ast-stats-2 - ImplicitSelf 192 ( 2.1%) 2 ast-stats-2 - Path 960 (10.5%) 10 -ast-stats-2 Item 2_024 (22.0%) 11 184 +ast-stats-2 Item 2_024 (22.1%) 11 184 ast-stats-2 - Trait 184 ( 2.0%) 1 ast-stats-2 - Enum 184 ( 2.0%) 1 ast-stats-2 - ExternCrate 184 ( 2.0%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Impl 184 ( 2.0%) 1 ast-stats-2 - Fn 368 ( 4.0%) 2 ast-stats-2 - Use 736 ( 8.0%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 9_184 +ast-stats-2 Total 9_144 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -121,7 +121,7 @@ hir-stats ---------------------------------------------------------------- hir-stats ForeignItemRef 24 ( 0.2%) 1 24 hir-stats Mod 32 ( 0.3%) 1 32 hir-stats ExprField 40 ( 0.4%) 1 40 -hir-stats TraitItemRef 56 ( 0.5%) 2 28 +hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats Param 64 ( 0.6%) 2 32 hir-stats Local 64 ( 0.6%) 1 64 hir-stats InlineAsm 72 ( 0.7%) 1 72 @@ -135,11 +135,11 @@ hir-stats - Semi 32 ( 0.3%) 1 hir-stats - Expr 32 ( 0.3%) 1 hir-stats FnDecl 120 ( 1.2%) 3 40 hir-stats Attribute 128 ( 1.3%) 4 32 +hir-stats GenericArg 128 ( 1.3%) 4 32 +hir-stats - Type 32 ( 0.3%) 1 +hir-stats - Lifetime 96 ( 0.9%) 3 hir-stats GenericArgs 144 ( 1.4%) 3 48 hir-stats Variant 160 ( 1.6%) 2 80 -hir-stats GenericArg 160 ( 1.6%) 4 40 -hir-stats - Type 40 ( 0.4%) 1 -hir-stats - Lifetime 120 ( 1.2%) 3 hir-stats GenericBound 192 ( 1.9%) 4 48 hir-stats - Trait 192 ( 1.9%) 4 hir-stats WherePredicate 216 ( 2.1%) 3 72 @@ -151,7 +151,7 @@ hir-stats - Wild 88 ( 0.9%) 1 hir-stats - Struct 88 ( 0.9%) 1 hir-stats - Binding 264 ( 2.6%) 3 hir-stats Generics 560 ( 5.5%) 10 56 -hir-stats Expr 768 ( 7.5%) 12 64 +hir-stats Expr 768 ( 7.6%) 12 64 hir-stats - Path 64 ( 0.6%) 1 hir-stats - Struct 64 ( 0.6%) 1 hir-stats - Match 64 ( 0.6%) 1 @@ -173,5 +173,5 @@ hir-stats - Path 936 ( 9.2%) 13 hir-stats Path 1_536 (15.1%) 32 48 hir-stats PathSegment 2_240 (22.0%) 40 56 hir-stats ---------------------------------------------------------------- -hir-stats Total 10_200 +hir-stats Total 10_168 hir-stats diff --git a/src/test/ui/structs-enums/type-sizes.rs b/src/test/ui/structs-enums/type-sizes.rs index 73a11a5e743..7a23f13630a 100644 --- a/src/test/ui/structs-enums/type-sizes.rs +++ b/src/test/ui/structs-enums/type-sizes.rs @@ -120,6 +120,54 @@ pub enum AlwaysTaggedBecauseItHasNoNiche { B } +pub enum NicheFilledMultipleFields { + A(bool, u8), + B(u8), + C(u8), + D(bool), + E, + F, + G, +} + +struct BoolInTheMiddle(std::num::NonZeroU16, bool, u8); + +enum NicheWithData { + A, + B([u16; 5]), + Largest { a1: u32, a2: BoolInTheMiddle, a3: u32 }, + C, + D(u32, u32), +} + +// A type with almost 2^16 invalid values. +#[repr(u16)] +pub enum NicheU16 { + _0, +} + +pub enum EnumManyVariant<X> { + Dataful(u8, X), + + // 0x100 niche variants. + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0A, _0B, _0C, _0D, _0E, _0F, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1A, _1B, _1C, _1D, _1E, _1F, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2A, _2B, _2C, _2D, _2E, _2F, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3A, _3B, _3C, _3D, _3E, _3F, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4A, _4B, _4C, _4D, _4E, _4F, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5A, _5B, _5C, _5D, _5E, _5F, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6A, _6B, _6C, _6D, _6E, _6F, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7B, _7C, _7D, _7E, _7F, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8A, _8B, _8C, _8D, _8E, _8F, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9A, _9B, _9C, _9D, _9E, _9F, + _A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8, _A9, _AA, _AB, _AC, _AD, _AE, _AF, + _B0, _B1, _B2, _B3, _B4, _B5, _B6, _B7, _B8, _B9, _BA, _BB, _BC, _BD, _BE, _BF, + _C0, _C1, _C2, _C3, _C4, _C5, _C6, _C7, _C8, _C9, _CA, _CB, _CC, _CD, _CE, _CF, + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7, _D8, _D9, _DA, _DB, _DC, _DD, _DE, _DF, + _E0, _E1, _E2, _E3, _E4, _E5, _E6, _E7, _E8, _E9, _EA, _EB, _EC, _ED, _EE, _EF, + _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, +} + pub fn main() { assert_eq!(size_of::<u8>(), 1 as usize); assert_eq!(size_of::<u32>(), 4 as usize); @@ -170,4 +218,35 @@ pub fn main() { assert_eq!(size_of::<AlwaysTaggedBecauseItHasNoNiche>(), 8); assert_eq!(size_of::<Option<AlwaysTaggedBecauseItHasNoNiche>>(), 8); assert_eq!(size_of::<Option<Option<AlwaysTaggedBecauseItHasNoNiche>>>(), 8); + + assert_eq!(size_of::<NicheFilledMultipleFields>(), 2); + assert_eq!(size_of::<Option<NicheFilledMultipleFields>>(), 2); + assert_eq!(size_of::<Option<Option<NicheFilledMultipleFields>>>(), 2); + + struct S1{ a: u16, b: std::num::NonZeroU16, c: u16, d: u8, e: u32, f: u64, g:[u8;2] } + assert_eq!(size_of::<S1>(), 24); + assert_eq!(size_of::<Option<S1>>(), 24); + + assert_eq!(size_of::<NicheWithData>(), 12); + assert_eq!(size_of::<Option<NicheWithData>>(), 12); + assert_eq!(size_of::<Option<Option<NicheWithData>>>(), 12); + assert_eq!( + size_of::<Option<Option2<&(), Option<NicheWithData>>>>(), + size_of::<(&(), NicheWithData)>() + ); + + pub enum FillPadding { A(std::num::NonZeroU8, u32), B } + assert_eq!(size_of::<FillPadding>(), 8); + assert_eq!(size_of::<Option<FillPadding>>(), 8); + assert_eq!(size_of::<Option<Option<FillPadding>>>(), 8); + + assert_eq!(size_of::<Result<(std::num::NonZeroU8, u8, u8), u16>>(), 4); + assert_eq!(size_of::<Option<Result<(std::num::NonZeroU8, u8, u8), u16>>>(), 4); + assert_eq!(size_of::<Result<(std::num::NonZeroU8, u8, u8, u8), u16>>(), 4); + + assert_eq!(size_of::<EnumManyVariant<u16>>(), 6); + assert_eq!(size_of::<EnumManyVariant<NicheU16>>(), 4); + assert_eq!(size_of::<EnumManyVariant<Option<NicheU16>>>(), 4); + assert_eq!(size_of::<EnumManyVariant<Option2<NicheU16,u8>>>(), 6); + assert_eq!(size_of::<EnumManyVariant<Option<(NicheU16,u8)>>>(), 6); } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 0212c2d712c..e5d2ead6ad6 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -22,8 +22,8 @@ LL | | }); | |______^ help: consider adding an explicit lifetime bound... | -LL | fn func<T: Test + 'a>(foo: &Foo, t: T) { - | ++++ +LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) { + | +++ ++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 0d749f04bea..ed1b91676a2 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -47,8 +47,10 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | G: Get<T> + 'a, - | ++++ +LL ~ fn bar<'a, G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | where +LL ~ G: Get<T> + 'a, + | error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:52:5 @@ -74,8 +76,8 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | fn qux<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ++++ +LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | +++ ++++ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:61:9 @@ -101,8 +103,8 @@ LL | | } | |_________^ help: consider adding an explicit lifetime bound... | -LL | fn qux<'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ++++ +LL | fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | +++ ++++ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:73:5 @@ -130,8 +132,8 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | fn bat<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ++++ +LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | +++ ++++ error[E0621]: explicit lifetime required in the type of `dest` --> $DIR/missing-lifetimes-in-signature.rs:73:5 diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs index 661b5486adc..1a0f3c5e550 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.rs +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs @@ -24,5 +24,5 @@ enum Foo { fn main() { let x: Foo = Foo::D(123, 456); - let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered + let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `Foo::A(_)` not covered } diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index c571e17a7b3..feeaa89e76f 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -1,8 +1,8 @@ -error[E0005]: refutable pattern in local binding: `A(_)` not covered +error[E0005]: refutable pattern in local binding: `Foo::A(_)` not covered --> $DIR/uninhabited-irrefutable.rs:27:9 | LL | let Foo::D(_y, _z) = x; - | ^^^^^^^^^^^^^^ pattern `A(_)` not covered + | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index ae509aab152..d1ab7fb6796 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1175,7 +1175,7 @@ fn replace_types<'tcx>( if replaced.insert(param_ty.index) { for projection_predicate in projection_predicates { if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx) - && let ty::Term::Ty(term_ty) = projection_predicate.term + && let Some(term_ty) = projection_predicate.term.ty() && let ty::Param(term_param_ty) = term_ty.kind() { let item_def_id = projection_predicate.projection_ty.item_def_id; diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index fc9ba15d82a..48a9d6e7c32 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3304,9 +3304,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // one of the associated types must be Self for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { - let assoc_ty = match projection_predicate.term { - ty::Term::Ty(ty) => ty, - ty::Term::Const(_c) => continue, + let assoc_ty = match projection_predicate.term.unpack() { + ty::TermKind::Ty(ty) => ty, + ty::TermKind::Const(_c) => continue, }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 9dceb9af2f2..85da97a39f9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -274,7 +274,7 @@ fn check_other_call_arg<'tcx>( .subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term); implements_trait(cx, receiver_ty, deref_trait_id, &[]) && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") - .map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty) + .map_or(false, |ty| ty::TermKind::Ty(ty) == normalized_ty.unpack()) } else { false } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 74c222bbcbe..b22a9c81746 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ Body, CastKind, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + TerminatorKind, NonDivergingIntrinsic }; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; @@ -212,11 +212,18 @@ fn check_statement<'tcx>( check_place(tcx, **place, span, body) }, - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => { + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => { + check_operand(tcx, op, span, body) + }, + + StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + rustc_middle::mir::CopyNonOverlapping { dst, src, count }, + )) => { check_operand(tcx, dst, span, body)?; check_operand(tcx, src, span, body)?; check_operand(tcx, count, span, body) }, + // These are all NOPs StatementKind::StorageLive(_) | StatementKind::StorageDead(_) diff --git a/src/tools/miri b/src/tools/miri -Subproject dba35d2be72f4b78343d1a0f0b4737306f31067 +Subproject ef3f649e49607a1fad64eb0a5139110df3efa2a diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index a70252fa65a..1563ee0b143 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -6,15 +6,15 @@ on: pull_request: push: branches: - - auto - - try + - auto + - try env: CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 CI: 1 RUST_BACKTRACE: short - RUSTFLAGS: "-D warnings -W unreachable-pub -W rust-2021-compatibility" + RUSTFLAGS: "-D warnings -W unreachable-pub -W bare-trait-objects" RUSTUP_MAX_RETRIES: 10 jobs: @@ -31,25 +31,25 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - - name: Checkout repository - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 20 + - name: Checkout repository + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 20 - - name: Install Rust toolchain - run: | - rustup update --no-self-update stable - rustup component add rustfmt rust-src + - name: Install Rust toolchain + run: | + rustup update --no-self-update stable + rustup component add rustfmt rust-src - - name: Cache Dependencies - uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72 + - name: Cache Dependencies + uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72 - - name: Compile - run: cargo test --no-run --locked + - name: Compile + run: cargo test --no-run --locked - - name: Test - run: cargo test -- --nocapture --quiet + - name: Test + run: cargo test -- --nocapture --quiet # Weird targets to catch non-portable code rust-cross: @@ -64,25 +64,25 @@ jobs: targets_ide: "wasm32-unknown-unknown" steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install Rust toolchain - run: | - rustup update --no-self-update stable - rustup target add ${{ env.targets }} ${{ env.targets_ide }} - - - name: Cache Dependencies - uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72 - - - name: Check - run: | - for target in ${{ env.targets }}; do - cargo check --target=$target --all-targets - done - for target in ${{ env.targets_ide }}; do - cargo check -p ide --target=$target --all-targets - done + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Rust toolchain + run: | + rustup update --no-self-update stable + rustup target add ${{ env.targets }} ${{ env.targets_ide }} + + - name: Cache Dependencies + uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72 + + - name: Check + run: | + for target in ${{ env.targets }}; do + cargo check --target=$target --all-targets + done + for target in ${{ env.targets_ide }}; do + cargo check -p ide --target=$target --all-targets + done typescript: if: github.repository == 'rust-lang/rust-analyzer' @@ -95,47 +95,47 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install Nodejs - uses: actions/setup-node@v1 - with: - node-version: 16.x - - - name: Install xvfb - if: matrix.os == 'ubuntu-latest' - run: sudo apt-get install -y xvfb - - - run: npm ci - working-directory: ./editors/code - -# - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } -# if: runner.os == 'Linux' -# working-directory: ./editors/code - - - run: npm run lint - working-directory: ./editors/code - - - name: Run VS Code tests (Linux) - if: matrix.os == 'ubuntu-latest' - env: - VSCODE_CLI: 1 - run: xvfb-run npm test - working-directory: ./editors/code - - - name: Run VS Code tests (Windows) - if: matrix.os == 'windows-latest' - env: - VSCODE_CLI: 1 - run: npm test - working-directory: ./editors/code - - - run: npm run pretest - working-directory: ./editors/code - - - run: npm run package --scripts-prepend-node-path - working-directory: ./editors/code + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Nodejs + uses: actions/setup-node@v1 + with: + node-version: 16.x + + - name: Install xvfb + if: matrix.os == 'ubuntu-latest' + run: sudo apt-get install -y xvfb + + - run: npm ci + working-directory: ./editors/code + + # - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } + # if: runner.os == 'Linux' + # working-directory: ./editors/code + + - run: npm run lint + working-directory: ./editors/code + + - name: Run VS Code tests (Linux) + if: matrix.os == 'ubuntu-latest' + env: + VSCODE_CLI: 1 + run: xvfb-run npm test + working-directory: ./editors/code + + - name: Run VS Code tests (Windows) + if: matrix.os == 'windows-latest' + env: + VSCODE_CLI: 1 + run: npm test + working-directory: ./editors/code + + - run: npm run pretest + working-directory: ./editors/code + + - run: npm run package --scripts-prepend-node-path + working-directory: ./editors/code end-success: name: bors build finished diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml index b2e5db6f689..303a10615bb 100644 --- a/src/tools/rust-analyzer/.github/workflows/release.yaml +++ b/src/tools/rust-analyzer/.github/workflows/release.yaml @@ -248,7 +248,7 @@ jobs: if: github.ref == 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer') working-directory: ./editors/code # token from https://dev.azure.com/rust-analyzer/ - run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix + run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true - name: Publish Extension (Code Marketplace, nightly) if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer') @@ -258,4 +258,4 @@ jobs: - name: Publish Extension (OpenVSX, nightly) if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer') working-directory: ./editors/code - run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix + run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index 1d818d96267..22f5fb99266 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -250,6 +250,10 @@ pub type PatSource = InFile<PatPtr>; pub type LabelPtr = AstPtr<ast::Label>; pub type LabelSource = InFile<LabelPtr>; + +pub type FieldPtr = AstPtr<ast::RecordExprField>; +pub type FieldSource = InFile<FieldPtr>; + /// An item body together with the mapping from syntax nodes to HIR expression /// IDs. This is needed to go from e.g. a position in a file to the HIR /// expression containing it; but for type inference etc., we want to operate on @@ -264,18 +268,18 @@ pub type LabelSource = InFile<LabelPtr>; #[derive(Default, Debug, Eq, PartialEq)] pub struct BodySourceMap { expr_map: FxHashMap<ExprSource, ExprId>, - expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, + expr_map_back: ArenaMap<ExprId, ExprSource>, pat_map: FxHashMap<PatSource, PatId>, - pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, + pat_map_back: ArenaMap<PatId, PatSource>, label_map: FxHashMap<LabelSource, LabelId>, label_map_back: ArenaMap<LabelId, LabelSource>, /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). /// Instead, we use id of expression (`92`) to identify the field. - field_map: FxHashMap<InFile<AstPtr<ast::RecordExprField>>, ExprId>, - field_map_back: FxHashMap<ExprId, InFile<AstPtr<ast::RecordExprField>>>, + field_map: FxHashMap<FieldSource, ExprId>, + field_map_back: FxHashMap<ExprId, FieldSource>, expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, @@ -420,7 +424,7 @@ impl Index<LabelId> for Body { // Perhaps `expr_syntax` and `expr_id`? impl BodySourceMap { pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { - self.expr_map_back[expr].clone() + self.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax) } pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { @@ -434,7 +438,7 @@ impl BodySourceMap { } pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { - self.pat_map_back[pat].clone() + self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax) } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { @@ -456,9 +460,10 @@ impl BodySourceMap { self.label_map.get(&src).cloned() } - pub fn field_syntax(&self, expr: ExprId) -> InFile<AstPtr<ast::RecordExprField>> { + pub fn field_syntax(&self, expr: ExprId) -> FieldSource { self.field_map_back[&expr].clone() } + pub fn node_field(&self, node: InFile<&ast::RecordExprField>) -> Option<ExprId> { let src = node.map(AstPtr::new); self.field_map.get(&src).cloned() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index f6ec8bf7e9e..3b3297f7811 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -24,7 +24,7 @@ use syntax::{ use crate::{ adt::StructKind, - body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, + body::{Body, BodySourceMap, Expander, ExprPtr, LabelPtr, LabelSource, PatPtr}, body::{BodyDiagnostic, ExprSource, PatSource}, builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, db::DefDatabase, @@ -150,21 +150,21 @@ impl ExprCollector<'_> { LowerCtx::new(self.db, self.expander.current_file_id) } - fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { + fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { let src = self.expander.to_source(ptr); - let id = self.make_expr(expr, Ok(src.clone())); + let id = self.make_expr(expr, src.clone()); self.source_map.expr_map.insert(src, id); id } // desugared exprs don't have ptr, that's wrong and should be fixed // somehow. fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { - self.make_expr(expr, Err(SyntheticSyntax)) + self.body.exprs.alloc(expr) } fn missing_expr(&mut self) -> ExprId { self.alloc_expr_desugared(Expr::Missing) } - fn make_expr(&mut self, expr: Expr, src: Result<ExprSource, SyntheticSyntax>) -> ExprId { + fn make_expr(&mut self, expr: Expr, src: ExprSource) -> ExprId { let id = self.body.exprs.alloc(expr); self.source_map.expr_map_back.insert(id, src); id @@ -172,20 +172,20 @@ impl ExprCollector<'_> { fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let src = self.expander.to_source(ptr); - let id = self.make_pat(pat, Ok(src.clone())); + let id = self.make_pat(pat, src.clone()); self.source_map.pat_map.insert(src, id); id } fn missing_pat(&mut self) -> PatId { - self.make_pat(Pat::Missing, Err(SyntheticSyntax)) + self.body.pats.alloc(Pat::Missing) } - fn make_pat(&mut self, pat: Pat, src: Result<PatSource, SyntheticSyntax>) -> PatId { + fn make_pat(&mut self, pat: Pat, src: PatSource) -> PatId { let id = self.body.pats.alloc(pat); self.source_map.pat_map_back.insert(id, src); id } - fn alloc_label(&mut self, label: Label, ptr: AstPtr<ast::Label>) -> LabelId { + fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId { let src = self.expander.to_source(ptr); let id = self.make_label(label, src.clone()); self.source_map.label_map.insert(src, id); @@ -550,20 +550,6 @@ impl ExprCollector<'_> { None => self.alloc_expr(Expr::Missing, syntax_ptr), } } - ast::Expr::MacroStmts(e) => { - let statements: Box<[_]> = - e.statements().filter_map(|s| self.collect_stmt(s)).collect(); - let tail = e.expr().map(|e| self.collect_expr(e)); - - if e.syntax().children().next().is_none() { - // HACK: make sure that macros that expand to nothing aren't treated as a `()` - // expression when used in block tail position. - cov_mark::hit!(empty_macro_in_trailing_position_is_removed); - return None; - } - - self.alloc_expr(Expr::MacroStmts { tail, statements }, syntax_ptr) - } ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), }) } @@ -640,11 +626,46 @@ impl ExprCollector<'_> { } } - fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Statement> { + fn collect_macro_as_stmt( + &mut self, + statements: &mut Vec<Statement>, + mac: ast::MacroExpr, + ) -> Option<ExprId> { + let mac_call = mac.macro_call()?; + let syntax_ptr = AstPtr::new(&ast::Expr::from(mac)); + let macro_ptr = AstPtr::new(&mac_call); + let expansion = self.collect_macro_call( + mac_call, + macro_ptr, + false, + |this, expansion: Option<ast::MacroStmts>| match expansion { + Some(expansion) => { + expansion.statements().for_each(|stmt| this.collect_stmt(statements, stmt)); + expansion.expr().and_then(|expr| match expr { + ast::Expr::MacroExpr(mac) => this.collect_macro_as_stmt(statements, mac), + expr => Some(this.collect_expr(expr)), + }) + } + None => None, + }, + ); + match expansion { + Some(tail) => { + // Make the macro-call point to its expanded expression so we can query + // semantics on syntax pointers to the macro + let src = self.expander.to_source(syntax_ptr); + self.source_map.expr_map.insert(src, tail); + Some(tail) + } + None => None, + } + } + + fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) { match s { ast::Stmt::LetStmt(stmt) => { if self.check_cfg(&stmt).is_none() { - return None; + return; } let pat = self.collect_pat_opt(stmt.pat()); let type_ref = @@ -654,61 +675,26 @@ impl ExprCollector<'_> { .let_else() .and_then(|let_else| let_else.block_expr()) .map(|block| self.collect_block(block)); - Some(Statement::Let { pat, type_ref, initializer, else_branch }) + statements.push(Statement::Let { pat, type_ref, initializer, else_branch }); } ast::Stmt::ExprStmt(stmt) => { let expr = stmt.expr(); - if let Some(expr) = &expr { - if self.check_cfg(expr).is_none() { - return None; - } + match &expr { + Some(expr) if self.check_cfg(expr).is_none() => return, + _ => (), } let has_semi = stmt.semicolon_token().is_some(); // Note that macro could be expanded to multiple statements - if let Some(expr @ ast::Expr::MacroExpr(mac)) = &expr { - let mac_call = mac.macro_call()?; - let syntax_ptr = AstPtr::new(expr); - let macro_ptr = AstPtr::new(&mac_call); - let stmt = self.collect_macro_call( - mac_call, - macro_ptr, - false, - |this, expansion: Option<ast::MacroStmts>| match expansion { - Some(expansion) => { - let statements = expansion - .statements() - .filter_map(|stmt| this.collect_stmt(stmt)) - .collect(); - let tail = expansion.expr().map(|expr| this.collect_expr(expr)); - - let mac_stmts = this.alloc_expr( - Expr::MacroStmts { tail, statements }, - AstPtr::new(&ast::Expr::MacroStmts(expansion)), - ); - - Some(mac_stmts) - } - None => None, - }, - ); - - let expr = match stmt { - Some(expr) => { - // Make the macro-call point to its expanded expression so we can query - // semantics on syntax pointers to the macro - let src = self.expander.to_source(syntax_ptr); - self.source_map.expr_map.insert(src, expr); - expr - } - None => self.alloc_expr(Expr::Missing, syntax_ptr), - }; - Some(Statement::Expr { expr, has_semi }) + if let Some(ast::Expr::MacroExpr(mac)) = expr { + if let Some(expr) = self.collect_macro_as_stmt(statements, mac) { + statements.push(Statement::Expr { expr, has_semi }) + } } else { let expr = self.collect_expr_opt(expr); - Some(Statement::Expr { expr, has_semi }) + statements.push(Statement::Expr { expr, has_semi }); } } - ast::Stmt::Item(_item) => None, + ast::Stmt::Item(_item) => (), } } @@ -729,9 +715,12 @@ impl ExprCollector<'_> { let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); let prev_local_module = mem::replace(&mut self.expander.module, module); - let mut statements: Vec<_> = - block.statements().filter_map(|s| self.collect_stmt(s)).collect(); - let tail = block.tail_expr().and_then(|e| self.maybe_collect_expr(e)); + let mut statements = Vec::new(); + block.statements().for_each(|s| self.collect_stmt(&mut statements, s)); + let tail = block.tail_expr().and_then(|e| match e { + ast::Expr::MacroExpr(mac) => self.collect_macro_as_stmt(&mut statements, mac), + expr => self.maybe_collect_expr(expr), + }); let tail = tail.or_else(|| { let stmt = statements.pop()?; if let Statement::Expr { expr, has_semi: false } = stmt { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index ddd476efe5c..f2fed954444 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -422,19 +422,6 @@ impl<'a> Printer<'a> { } w!(self, "}}"); } - Expr::MacroStmts { statements, tail } => { - w!(self, "{{ // macro statements"); - self.indented(|p| { - for stmt in statements.iter() { - p.print_stmt(stmt); - } - if let Some(tail) = tail { - p.print_expr(*tail); - } - }); - self.newline(); - w!(self, "}}"); - } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs index f4c390dce26..45f64ebb060 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs @@ -47,16 +47,9 @@ pub struct ScopeData { impl ExprScopes { pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> { let body = db.body(def); - Arc::new(ExprScopes::new(&*body)) - } - - fn new(body: &Body) -> ExprScopes { - let mut scopes = - ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; - let mut root = scopes.root_scope(); - scopes.add_params_bindings(body, root, &body.params); - compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root); - scopes + let mut scopes = ExprScopes::new(&*body); + scopes.shrink_to_fit(); + Arc::new(scopes) } pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { @@ -89,6 +82,17 @@ impl ExprScopes { pub fn scope_by_expr(&self) -> &FxHashMap<ExprId, ScopeId> { &self.scope_by_expr } +} + +impl ExprScopes { + fn new(body: &Body) -> ExprScopes { + let mut scopes = + ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; + let mut root = scopes.root_scope(); + scopes.add_params_bindings(body, root, &body.params); + compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root); + scopes + } fn root_scope(&mut self) -> ScopeId { self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] }) @@ -138,6 +142,13 @@ impl ExprScopes { fn set_scope(&mut self, node: ExprId, scope: ScopeId) { self.scope_by_expr.insert(node, scope); } + + fn shrink_to_fit(&mut self) { + let ExprScopes { scopes, scope_by_expr } = self; + scopes.shrink_to_fit(); + scopes.values_mut().for_each(|it| it.entries.shrink_to_fit()); + scope_by_expr.shrink_to_fit(); + } } fn compute_block_scopes( @@ -176,9 +187,6 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope scopes.set_scope(expr, *scope); match &body[expr] { - Expr::MacroStmts { statements, tail } => { - compute_block_scopes(statements, *tail, body, scopes, scope); - } Expr::Block { statements, tail, id, label } => { let mut scope = scopes.new_block_scope(*scope, *id, make_label(label)); // Overwrite the old scope for the block expr, so that every block scope can be found diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs index 4381b43c258..419d3feec3b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs @@ -206,10 +206,6 @@ pub enum Expr { Unsafe { body: ExprId, }, - MacroStmts { - statements: Box<[Statement]>, - tail: Option<ExprId>, - }, Array(Array), Literal(Literal), Underscore, @@ -263,7 +259,7 @@ impl Expr { Expr::Let { expr, .. } => { f(*expr); } - Expr::MacroStmts { tail, statements } | Expr::Block { statements, tail, .. } => { + Expr::Block { statements, tail, .. } => { for stmt in statements.iter() { match stmt { Statement::Let { initializer, .. } => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 6eb530ecc54..9b4ce9f97c8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -64,7 +64,7 @@ use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId}; use itertools::Itertools; use la_arena::Arena; use profile::Count; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use stdx::format_to; use syntax::{ast, SmolStr}; @@ -98,7 +98,11 @@ pub struct DefMap { /// The prelude module for this crate. This either comes from an import /// marked with the `prelude_import` attribute, or (in the normal case) from /// a dependency (`std` or `core`). + /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used, + /// but that attribute is nightly and when used in a block, it affects resolution globally + /// so we aren't handling this correctly anyways). prelude: Option<ModuleId>, + /// The extern prelude is only populated for non-block DefMaps extern_prelude: FxHashMap<Name, ModuleId>, /// Side table for resolving derive helpers. @@ -114,6 +118,8 @@ pub struct DefMap { registered_attrs: Vec<SmolStr>, /// Custom tool modules registered with `#![register_tool]`. registered_tools: Vec<SmolStr>, + /// Unstable features of Rust enabled with `#![feature(A, B)]`. + unstable_features: FxHashSet<SmolStr>, edition: Edition, recursion_limit: Option<u32>, @@ -284,6 +290,7 @@ impl DefMap { modules, registered_attrs: Vec::new(), registered_tools: Vec::new(), + unstable_features: FxHashSet::default(), diagnostics: Vec::new(), } } @@ -314,6 +321,10 @@ impl DefMap { &self.registered_attrs } + pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool { + self.unstable_features.contains(feature) + } + pub fn root(&self) -> LocalModuleId { self.root } @@ -479,6 +490,7 @@ impl DefMap { registered_tools, fn_proc_macro_mapping, derive_helpers_in_scope, + unstable_features, proc_macro_loading_error: _, block: _, edition: _, @@ -496,6 +508,7 @@ impl DefMap { registered_tools.shrink_to_fit(); fn_proc_macro_mapping.shrink_to_fit(); derive_helpers_in_scope.shrink_to_fit(); + unstable_features.shrink_to_fit(); for (_, module) in modules.iter_mut() { module.children.shrink_to_fit(); module.scope.shrink_to_fit(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 8a6bb929c3d..495bbe4579f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -294,6 +294,17 @@ impl DefCollector<'_> { continue; } + if *attr_name == hir_expand::name![feature] { + let features = + attr.parse_path_comma_token_tree().into_iter().flatten().filter_map( + |feat| match feat.segments() { + [name] => Some(name.to_smol_str()), + _ => None, + }, + ); + self.def_map.unstable_features.extend(features); + } + let attr_is_register_like = *attr_name == hir_expand::name![register_attr] || *attr_name == hir_expand::name![register_tool]; if !attr_is_register_like { @@ -501,10 +512,9 @@ impl DefCollector<'_> { Edition::Edition2021 => name![rust_2021], }; - let path_kind = if self.def_map.edition == Edition::Edition2015 { - PathKind::Plain - } else { - PathKind::Abs + let path_kind = match self.def_map.edition { + Edition::Edition2015 => PathKind::Plain, + _ => PathKind::Abs, }; let path = ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter()); @@ -524,7 +534,6 @@ impl DefCollector<'_> { match per_ns.types { Some((ModuleDefId::ModuleId(m), _)) => { self.def_map.prelude = Some(m); - return; } types => { tracing::debug!( @@ -839,7 +848,10 @@ impl DefCollector<'_> { tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 - if import.is_extern_crate && module_id == self.def_map.root { + if import.is_extern_crate + && self.def_map.block.is_none() + && module_id == self.def_map.root + { if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name) { self.def_map.extern_prelude.insert(name.clone(), def); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs index 99f7f1b549e..ca7bcc814e8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs @@ -65,6 +65,7 @@ impl ModDir { name: &Name, attr_path: Option<&SmolStr>, ) -> Result<(FileId, bool, ModDir), Box<[String]>> { + let name = name.unescaped(); let orig_file_id = file_id.original_file(db.upcast()); let mut candidate_files = ArrayVec::<_, 2>::new(); @@ -73,12 +74,10 @@ impl ModDir { candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) } None if file_id.is_include_macro(db.upcast()) => { - let name = name.unescaped(); candidate_files.push(format!("{}.rs", name)); candidate_files.push(format!("{}/mod.rs", name)); } None => { - let name = name.unescaped(); candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs index 3fa585574de..ba3bf8b5a5c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs @@ -127,7 +127,15 @@ mod r#async; use self::r#async::Bar; //- /async.rs +mod foo; +mod r#async; pub struct Bar; + +//- /async/foo.rs +pub struct Foo; + +//- /async/async.rs +pub struct Baz; "#, expect![[r#" crate @@ -136,6 +144,14 @@ pub struct Bar; crate::r#async Bar: t v + foo: t + r#async: t + + crate::r#async::foo + Foo: t v + + crate::r#async::r#async + Baz: t v "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 3163fa0f93f..8aa5973cac5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -31,12 +31,10 @@ pub struct Resolver { /// /// When using, you generally want to process the scopes in reverse order, /// there's `scopes` *method* for that. - /// - /// Invariant: There exists at least one Scope::ModuleScope at the start of the vec. scopes: Vec<Scope>, + module_scope: ModuleItemMap, } -// FIXME how to store these best #[derive(Debug, Clone)] struct ModuleItemMap { def_map: Arc<DefMap>, @@ -53,7 +51,7 @@ struct ExprScope { #[derive(Debug, Clone)] enum Scope { /// All the items and imported names of a module - ModuleScope(ModuleItemMap), + BlockScope(ModuleItemMap), /// Brings the generic parameters of an item into scope GenericParams { def: GenericDefId, params: Interned<GenericParams> }, /// Brings `Self` in `impl` block into scope @@ -127,24 +125,6 @@ impl Resolver { } } - fn scopes(&self) -> impl Iterator<Item = &Scope> { - self.scopes.iter().rev() - } - - fn resolve_module_path( - &self, - db: &dyn DefDatabase, - path: &ModPath, - shadow: BuiltinShadowMode, - ) -> PerNs { - let (item_map, module) = self.module_scope(); - let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); - if segment_index.is_some() { - return PerNs::none(); - } - module_res - } - pub fn resolve_module_path_in_items(&self, db: &dyn DefDatabase, path: &ModPath) -> PerNs { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } @@ -155,7 +135,7 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, ) -> Option<PerNs> { - let (item_map, module) = self.module_scope(); + let (item_map, module) = self.item_scope(); let (module_res, idx) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module); match module_res.take_types()? { ModuleDefId::TraitId(it) => { @@ -183,37 +163,38 @@ impl Resolver { ) -> Option<(TypeNs, Option<usize>)> { let first_name = path.segments().first()?; let skip_to_mod = path.kind != PathKind::Plain; + if skip_to_mod { + return self.module_scope.resolve_path_in_type_ns(db, path); + } + + let remaining_idx = || if path.segments().len() == 1 { None } else { Some(1) }; + for scope in self.scopes() { match scope { Scope::ExprScope(_) => continue, - Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue, - Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { - let idx = if path.segments().len() == 1 { None } else { Some(1) }; - return Some((TypeNs::GenericParam(id), idx)); + return Some((TypeNs::GenericParam(id), remaining_idx())); } } - Scope::ImplDefScope(impl_) => { + &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - let idx = if path.segments().len() == 1 { None } else { Some(1) }; - return Some((TypeNs::SelfType(*impl_), idx)); + return Some((TypeNs::SelfType(impl_), remaining_idx())); } } - Scope::AdtScope(adt) => { + &Scope::AdtScope(adt) => { if first_name == &name![Self] { - let idx = if path.segments().len() == 1 { None } else { Some(1) }; - return Some((TypeNs::AdtSelfType(*adt), idx)); + return Some((TypeNs::AdtSelfType(adt), remaining_idx())); } } - Scope::ModuleScope(m) => { + Scope::BlockScope(m) => { if let Some(res) = m.resolve_path_in_type_ns(db, path) { return Some(res); } } } } - None + self.module_scope.resolve_path_in_type_ns(db, path) } pub fn resolve_path_in_type_ns_fully( @@ -235,7 +216,7 @@ impl Resolver { ) -> Option<Visibility> { match visibility { RawVisibility::Module(_) => { - let (item_map, module) = self.module_scope(); + let (item_map, module) = self.item_scope(); item_map.resolve_visibility(db, module, visibility) } RawVisibility::Public => Some(Visibility::Public), @@ -251,18 +232,14 @@ impl Resolver { let tmp = name![self]; let first_name = if path.is_self() { &tmp } else { path.segments().first()? }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); + if skip_to_mod { + return self.module_scope.resolve_path_in_value_ns(db, path); + } + for scope in self.scopes() { match scope { - Scope::AdtScope(_) - | Scope::ExprScope(_) - | Scope::GenericParams { .. } - | Scope::ImplDefScope(_) - if skip_to_mod => - { - continue - } - - Scope::ExprScope(scope) if n_segments <= 1 => { + Scope::ExprScope(_) if n_segments > 1 => continue, + Scope::ExprScope(scope) => { let entry = scope .expr_scopes .entries(scope.scope_id) @@ -273,44 +250,39 @@ impl Resolver { return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat()))); } } - Scope::ExprScope(_) => continue, - Scope::GenericParams { params, def } if n_segments > 1 => { if let Some(id) = params.find_type_by_name(first_name, *def) { let ty = TypeNs::GenericParam(id); return Some(ResolveValueResult::Partial(ty, 1)); } } - Scope::GenericParams { params, def } if n_segments == 1 => { + Scope::GenericParams { .. } if n_segments != 1 => continue, + Scope::GenericParams { params, def } => { if let Some(id) = params.find_const_by_name(first_name, *def) { let val = ValueNs::GenericParam(id); return Some(ResolveValueResult::ValueNs(val)); } } - Scope::GenericParams { .. } => continue, - Scope::ImplDefScope(impl_) => { + &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - if n_segments > 1 { - let ty = TypeNs::SelfType(*impl_); - return Some(ResolveValueResult::Partial(ty, 1)); + return Some(if n_segments > 1 { + ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1) } else { - return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(*impl_))); - } + ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_)) + }); } } + // bare `Self` doesn't work in the value namespace in a struct/enum definition + Scope::AdtScope(_) if n_segments == 1 => continue, Scope::AdtScope(adt) => { - if n_segments == 1 { - // bare `Self` doesn't work in the value namespace in a struct/enum definition - continue; - } if first_name == &name![Self] { let ty = TypeNs::AdtSelfType(*adt); return Some(ResolveValueResult::Partial(ty, 1)); } } - Scope::ModuleScope(m) => { + Scope::BlockScope(m) => { if let Some(def) = m.resolve_path_in_value_ns(db, path) { return Some(def); } @@ -318,15 +290,16 @@ impl Resolver { } } + if let res @ Some(_) = self.module_scope.resolve_path_in_value_ns(db, path) { + return res; + } + // If a path of the shape `u16::from_le_bytes` failed to resolve at all, then we fall back // to resolving to the primitive type, to allow this to still work in the presence of // `use core::u16;`. if path.kind == PathKind::Plain && path.segments().len() > 1 { - match BuiltinType::by_name(&path.segments()[0]) { - Some(builtin) => { - return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1)); - } - None => {} + if let Some(builtin) = BuiltinType::by_name(&path.segments()[0]) { + return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1)); } } @@ -345,7 +318,7 @@ impl Resolver { } pub fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> { - let (item_map, module) = self.module_scope(); + let (item_map, module) = self.item_scope(); item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() } @@ -395,30 +368,43 @@ impl Resolver { for scope in self.scopes() { scope.process_names(&mut res, db); } + let ModuleItemMap { ref def_map, module_id } = self.module_scope; + // FIXME: should we provide `self` here? + // f( + // Name::self_param(), + // PerNs::types(Resolution::Def { + // def: m.module.into(), + // }), + // ); + def_map[module_id].scope.entries().for_each(|(name, def)| { + res.add_per_ns(name, def); + }); + def_map[module_id].scope.legacy_macros().for_each(|(name, macs)| { + macs.iter().for_each(|&mac| { + res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac)))); + }) + }); + def_map.extern_prelude().for_each(|(name, &def)| { + res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); + }); + BUILTIN_SCOPE.iter().for_each(|(name, &def)| { + res.add_per_ns(name, def); + }); + if let Some(prelude) = def_map.prelude() { + let prelude_def_map = prelude.def_map(db); + for (name, def) in prelude_def_map[prelude.local_id].scope.entries() { + res.add_per_ns(name, def) + } + } res.map } pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> { let mut traits = FxHashSet::default(); + for scope in self.scopes() { match scope { - Scope::ModuleScope(m) => { - if let Some(prelude) = m.def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - traits.extend(prelude_def_map[prelude.local_id].scope.traits()); - } - traits.extend(m.def_map[m.module_id].scope.traits()); - - // Add all traits that are in scope because of the containing DefMaps - m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { - if let Some(prelude) = def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - traits.extend(prelude_def_map[prelude.local_id].scope.traits()); - } - traits.extend(def_map[module].scope.traits()); - None::<()> - }); - } + Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()), &Scope::ImplDefScope(impl_) => { if let Some(target_trait) = &db.impl_data(impl_).target_trait { if let Some(TypeNs::TraitId(trait_)) = @@ -431,35 +417,28 @@ impl Resolver { _ => (), } } - traits - } - fn module_scope(&self) -> (&DefMap, LocalModuleId) { - self.scopes() - .find_map(|scope| match scope { - Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)), - _ => None, - }) - .expect("module scope invariant violated") + // Fill in the prelude traits + if let Some(prelude) = self.module_scope.def_map.prelude() { + let prelude_def_map = prelude.def_map(db); + traits.extend(prelude_def_map[prelude.local_id].scope.traits()); + } + // Fill in module visible traits + traits.extend(self.module_scope.def_map[self.module_scope.module_id].scope.traits()); + traits } pub fn module(&self) -> ModuleId { - let (def_map, local_id) = self.module_scope(); + let (def_map, local_id) = self.item_scope(); def_map.module_id(local_id) } pub fn krate(&self) -> CrateId { - self.def_map().krate() + self.module_scope.def_map.krate() } pub fn def_map(&self) -> &DefMap { - self.scopes - .get(0) - .and_then(|scope| match scope { - Scope::ModuleScope(m) => Some(&m.def_map), - _ => None, - }) - .expect("module scope invariant violated") + self.item_scope().0 } pub fn where_predicates_in_scope( @@ -488,6 +467,36 @@ impl Resolver { } } +impl Resolver { + fn scopes(&self) -> impl Iterator<Item = &Scope> { + self.scopes.iter().rev() + } + + fn resolve_module_path( + &self, + db: &dyn DefDatabase, + path: &ModPath, + shadow: BuiltinShadowMode, + ) -> PerNs { + let (item_map, module) = self.item_scope(); + let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); + if segment_index.is_some() { + return PerNs::none(); + } + module_res + } + + /// The innermost block scope that contains items or the module scope that contains this resolver. + fn item_scope(&self) -> (&DefMap, LocalModuleId) { + self.scopes() + .find_map(|scope| match scope { + Scope::BlockScope(m) => Some((&*m.def_map, m.module_id)), + _ => None, + }) + .unwrap_or((&self.module_scope.def_map, self.module_scope.module_id)) + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ScopeDef { ModuleDef(ModuleDefId), @@ -502,14 +511,7 @@ pub enum ScopeDef { impl Scope { fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) { match self { - Scope::ModuleScope(m) => { - // FIXME: should we provide `self` here? - // f( - // Name::self_param(), - // PerNs::types(Resolution::Def { - // def: m.module.into(), - // }), - // ); + Scope::BlockScope(m) => { m.def_map[m.module_id].scope.entries().for_each(|(name, def)| { acc.add_per_ns(name, def); }); @@ -521,18 +523,6 @@ impl Scope { ); }) }); - m.def_map.extern_prelude().for_each(|(name, &def)| { - acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); - }); - BUILTIN_SCOPE.iter().for_each(|(name, &def)| { - acc.add_per_ns(name, def); - }); - if let Some(prelude) = m.def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - for (name, def) in prelude_def_map[prelude.local_id].scope.entries() { - acc.add_per_ns(name, def) - } - } } Scope::GenericParams { params, def: parent } => { let parent = *parent; @@ -596,7 +586,7 @@ pub fn resolver_for_scope( if let Some(block) = scopes.block(scope) { if let Some(def_map) = db.block_def_map(block) { let root = def_map.root(); - r = r.push_module_scope(def_map, root); + r = r.push_block_scope(def_map, root); // FIXME: This adds as many module scopes as there are blocks, but resolving in each // already traverses all parents, so this is O(n²). I think we could only store the // innermost module scope instead? @@ -623,8 +613,8 @@ impl Resolver { self.push_scope(Scope::ImplDefScope(impl_def)) } - fn push_module_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver { - self.push_scope(Scope::ModuleScope(ModuleItemMap { def_map, module_id })) + fn push_block_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver { + self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id })) } fn push_expr_scope( @@ -768,14 +758,19 @@ pub trait HasResolver: Copy { impl HasResolver for ModuleId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { let mut def_map = self.def_map(db); - let mut modules: SmallVec<[_; 2]> = smallvec![(def_map.clone(), self.local_id)]; + let mut modules: SmallVec<[_; 1]> = smallvec![]; + let mut module_id = self.local_id; while let Some(parent) = def_map.parent() { + modules.push((def_map, module_id)); def_map = parent.def_map(db); - modules.push((def_map.clone(), parent.local_id)); + module_id = parent.local_id; } - let mut resolver = Resolver { scopes: Vec::with_capacity(modules.len()) }; + let mut resolver = Resolver { + scopes: Vec::with_capacity(modules.len()), + module_scope: ModuleItemMap { def_map, module_id }, + }; for (def_map, module) in modules.into_iter().rev() { - resolver = resolver.push_module_scope(def_map, module); + resolver = resolver.push_block_scope(def_map, module); } resolver } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index d753d88470c..fc128102f22 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -969,7 +969,7 @@ impl ExpandTo { if parent.kind() == MACRO_EXPR && parent .parent() - .map_or(true, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS)) + .map_or(false, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS)) { return ExpandTo::Statements; } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 2b859f77509..4ce21a57967 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -336,6 +336,7 @@ pub mod known { test, test_case, recursion_limit, + feature, // Safe intrinsics abort, add_with_overflow, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index b6f226dbfd2..344036dd813 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -104,8 +104,7 @@ pub(crate) fn deref(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> { fn builtin_deref(ty: &Ty) -> Option<&Ty> { match ty.kind(Interner) { - TyKind::Ref(.., ty) => Some(ty), - TyKind::Raw(.., ty) => Some(ty), + TyKind::Ref(.., ty) | TyKind::Raw(.., ty) => Some(ty), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 642e03edd23..c8df4c796ef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -159,12 +159,7 @@ impl ExprValidator { } let pattern_arena = Arena::new(); - let cx = MatchCheckCtx { - module: self.owner.module(db.upcast()), - body: self.owner, - db, - pattern_arena: &pattern_arena, - }; + let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db, &pattern_arena); let mut m_arms = Vec::with_capacity(arms.len()); let mut has_lowering_errors = false; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs index bbbe539c13f..47d60fc41e7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs @@ -52,7 +52,10 @@ use hir_def::{EnumVariantId, HasModule, LocalFieldId, VariantId}; use smallvec::{smallvec, SmallVec}; use stdx::never; -use crate::{infer::normalize, AdtId, Interner, Scalar, Ty, TyExt, TyKind}; +use crate::{ + infer::normalize, inhabitedness::is_enum_variant_uninhabited_from, AdtId, Interner, Scalar, Ty, + TyExt, TyKind, +}; use super::{ is_box, @@ -557,8 +560,8 @@ impl SplitWildcard { TyKind::Scalar(Scalar::Bool) => smallvec![make_range(0, 1, Scalar::Bool)], // TyKind::Array(..) if ... => unhandled(), TyKind::Array(..) | TyKind::Slice(..) => unhandled(), - &TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { - let enum_data = cx.db.enum_data(enum_id); + TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), subst) => { + let enum_data = cx.db.enum_data(*enum_id); // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an // additional "unknown" constructor. @@ -591,14 +594,15 @@ impl SplitWildcard { let mut ctors: SmallVec<[_; 1]> = enum_data .variants .iter() - .filter(|&(_, _v)| { + .map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id }) + .filter(|&variant| { // If `exhaustive_patterns` is enabled, we exclude variants known to be // uninhabited. let is_uninhabited = is_exhaustive_pat_feature - && unimplemented!("after MatchCheckCtx.feature_exhaustive_patterns()"); + && is_enum_variant_uninhabited_from(variant, subst, cx.module, cx.db); !is_uninhabited }) - .map(|(local_id, _)| Variant(EnumVariantId { parent: enum_id, local_id })) + .map(Variant) .collect(); if is_secretly_empty || is_declared_nonexhaustive { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/usefulness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/usefulness.rs index 1221327b951..c4d709a975b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/usefulness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/usefulness.rs @@ -277,7 +277,7 @@ use hir_def::{AdtId, DefWithBodyId, HasModule, ModuleId}; use smallvec::{smallvec, SmallVec}; use typed_arena::Arena; -use crate::{db::HirDatabase, Ty, TyExt}; +use crate::{db::HirDatabase, inhabitedness::is_ty_uninhabited_from, Ty, TyExt}; use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard}; @@ -289,13 +289,27 @@ pub(crate) struct MatchCheckCtx<'a, 'p> { pub(crate) db: &'a dyn HirDatabase, /// Lowered patterns from arms plus generated by the check. pub(crate) pattern_arena: &'p Arena<DeconstructedPat<'p>>, + exhaustive_patterns: bool, } impl<'a, 'p> MatchCheckCtx<'a, 'p> { - pub(super) fn is_uninhabited(&self, _ty: &Ty) -> bool { - // FIXME(iDawer) implement exhaustive_patterns feature. More info in: - // Tracking issue for RFC 1872: exhaustive_patterns feature https://github.com/rust-lang/rust/issues/51085 - false + pub(crate) fn new( + module: ModuleId, + body: DefWithBodyId, + db: &'a dyn HirDatabase, + pattern_arena: &'p Arena<DeconstructedPat<'p>>, + ) -> Self { + let def_map = db.crate_def_map(module.krate()); + let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); + Self { module, body, db, pattern_arena, exhaustive_patterns } + } + + pub(super) fn is_uninhabited(&self, ty: &Ty) -> bool { + if self.feature_exhaustive_patterns() { + is_ty_uninhabited_from(ty, self.module, self.db) + } else { + false + } } /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. @@ -311,10 +325,9 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> { } } - // Rust feature described as "Allows exhaustive pattern matching on types that contain uninhabited types." + // Rust's unstable feature described as "Allows exhaustive pattern matching on types that contain uninhabited types." pub(super) fn feature_exhaustive_patterns(&self) -> bool { - // FIXME see MatchCheckCtx::is_uninhabited - false + self.exhaustive_patterns } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 5df48e5fdcb..10ffde87eef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -182,7 +182,7 @@ pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>; #[derive(Debug, PartialEq, Eq, Clone)] pub enum InferenceDiagnostic { NoSuchField { expr: ExprId }, - BreakOutsideOfLoop { expr: ExprId }, + BreakOutsideOfLoop { expr: ExprId, is_break: bool }, MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize }, } @@ -418,18 +418,45 @@ pub(crate) struct InferenceContext<'a> { #[derive(Clone, Debug)] struct BreakableContext { + /// Whether this context contains at least one break expression. may_break: bool, + /// The coercion target of the context. coerce: CoerceMany, + /// The optional label of the context. label: Option<name::Name>, + kind: BreakableKind, +} + +#[derive(Clone, Debug)] +enum BreakableKind { + Block, + Loop, + /// A border is something like an async block, closure etc. Anything that prevents + /// breaking/continuing through + Border, } fn find_breakable<'c>( ctxs: &'c mut [BreakableContext], label: Option<&name::Name>, ) -> Option<&'c mut BreakableContext> { + let mut ctxs = ctxs + .iter_mut() + .rev() + .take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop)); + match label { + Some(_) => ctxs.find(|ctx| ctx.label.as_ref() == label), + None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)), + } +} + +fn find_continuable<'c>( + ctxs: &'c mut [BreakableContext], + label: Option<&name::Name>, +) -> Option<&'c mut BreakableContext> { match label { - Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label), - None => ctxs.last_mut(), + Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)), + None => find_breakable(ctxs, label), } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 2a13106390d..2d04a864a2c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -10,7 +10,7 @@ use chalk_ir::{ cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind, }; use hir_def::{ - expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, Literal, Statement, UnaryOp}, + expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, LabelId, Literal, Statement, UnaryOp}, generics::TypeOrConstParamData, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, @@ -23,7 +23,7 @@ use syntax::ast::RangeOp; use crate::{ autoderef::{self, Autoderef}, consteval, - infer::coerce::CoerceMany, + infer::{coerce::CoerceMany, find_continuable, BreakableKind}, lower::{ const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode, }, @@ -120,32 +120,37 @@ impl<'a> InferenceContext<'a> { let ty = match label { Some(_) => { let break_ty = self.table.new_type_var(); - self.breakables.push(BreakableContext { - may_break: false, - coerce: CoerceMany::new(break_ty.clone()), - label: label.map(|label| self.body[label].name.clone()), - }); - let ty = self.infer_block( - tgt_expr, - statements, - *tail, - &Expectation::has_type(break_ty), + let (breaks, ty) = self.with_breakable_ctx( + BreakableKind::Block, + break_ty.clone(), + *label, + |this| { + this.infer_block( + tgt_expr, + statements, + *tail, + &Expectation::has_type(break_ty), + ) + }, ); - let ctxt = self.breakables.pop().expect("breakable stack broken"); - if ctxt.may_break { - ctxt.coerce.complete() - } else { - ty - } + breaks.unwrap_or(ty) } None => self.infer_block(tgt_expr, statements, *tail, expected), }; self.resolver = old_resolver; ty } - Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), + Expr::Unsafe { body } => self.infer_expr(*body, expected), + Expr::Const { body } => { + self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { + this.infer_expr(*body, expected) + }) + .1 + } Expr::TryBlock { body } => { - let _inner = self.infer_expr(*body, expected); + self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { + let _inner = this.infer_expr(*body, expected); + }); // FIXME should be std::result::Result<{inner}, _> self.err_ty() } @@ -154,7 +159,10 @@ impl<'a> InferenceContext<'a> { let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); - let inner_ty = self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); + let (_, inner_ty) = + self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { + this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)) + }); self.diverges = prev_diverges; self.return_ty = prev_ret_ty; @@ -166,54 +174,44 @@ impl<'a> InferenceContext<'a> { TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty)) .intern(Interner) } - Expr::Loop { body, label } => { - self.breakables.push(BreakableContext { - may_break: false, - coerce: CoerceMany::new(self.table.new_type_var()), - label: label.map(|label| self.body[label].name.clone()), - }); - self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); - - let ctxt = self.breakables.pop().expect("breakable stack broken"); + &Expr::Loop { body, label } => { + let ty = self.table.new_type_var(); + let (breaks, ()) = + self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| { + this.infer_expr(body, &Expectation::has_type(TyBuilder::unit())); + }); - if ctxt.may_break { - self.diverges = Diverges::Maybe; - ctxt.coerce.complete() - } else { - TyKind::Never.intern(Interner) + match breaks { + Some(breaks) => { + self.diverges = Diverges::Maybe; + breaks + } + None => TyKind::Never.intern(Interner), } } - Expr::While { condition, body, label } => { - self.breakables.push(BreakableContext { - may_break: false, - coerce: CoerceMany::new(self.err_ty()), - label: label.map(|label| self.body[label].name.clone()), + &Expr::While { condition, body, label } => { + self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| { + this.infer_expr( + condition, + &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)), + ); + this.infer_expr(body, &Expectation::has_type(TyBuilder::unit())); }); - self.infer_expr( - *condition, - &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)), - ); - self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); - let _ctxt = self.breakables.pop().expect("breakable stack broken"); + // the body may not run, so it diverging doesn't mean we diverge self.diverges = Diverges::Maybe; TyBuilder::unit() } - Expr::For { iterable, body, pat, label } => { - let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); - - self.breakables.push(BreakableContext { - may_break: false, - coerce: CoerceMany::new(self.err_ty()), - label: label.map(|label| self.body[label].name.clone()), - }); + &Expr::For { iterable, body, pat, label } => { + let iterable_ty = self.infer_expr(iterable, &Expectation::none()); let pat_ty = self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); - self.infer_pat(*pat, &pat_ty, BindingMode::default()); + self.infer_pat(pat, &pat_ty, BindingMode::default()); + self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| { + this.infer_expr(body, &Expectation::has_type(TyBuilder::unit())); + }); - self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); - let _ctxt = self.breakables.pop().expect("breakable stack broken"); // the body may not run, so it diverging doesn't mean we diverge self.diverges = Diverges::Maybe; TyBuilder::unit() @@ -269,7 +267,9 @@ impl<'a> InferenceContext<'a> { let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); - self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); + self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { + this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); + }); self.diverges = prev_diverges; self.return_ty = prev_ret_ty; @@ -372,37 +372,45 @@ impl<'a> InferenceContext<'a> { let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or_else(|| self.err_ty()) } - Expr::Continue { .. } => TyKind::Never.intern(Interner), - Expr::Break { expr, label } => { - let mut coerce = match find_breakable(&mut self.breakables, label.as_ref()) { - Some(ctxt) => { - // avoiding the borrowck - mem::replace( - &mut ctxt.coerce, - CoerceMany::new(self.result.standard_types.unknown.clone()), - ) - } - None => CoerceMany::new(self.result.standard_types.unknown.clone()), + Expr::Continue { label } => { + if let None = find_continuable(&mut self.breakables, label.as_ref()) { + self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { + expr: tgt_expr, + is_break: false, + }); }; - + TyKind::Never.intern(Interner) + } + Expr::Break { expr, label } => { let val_ty = if let Some(expr) = *expr { self.infer_expr(expr, &Expectation::none()) } else { TyBuilder::unit() }; - // FIXME: create a synthetic `()` during lowering so we have something to refer to here? - coerce.coerce(self, *expr, &val_ty); + match find_breakable(&mut self.breakables, label.as_ref()) { + Some(ctxt) => { + // avoiding the borrowck + let mut coerce = mem::replace( + &mut ctxt.coerce, + CoerceMany::new(self.result.standard_types.unknown.clone()), + ); - if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { - ctxt.coerce = coerce; - ctxt.may_break = true; - } else { - self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { - expr: tgt_expr, - }); - }; + // FIXME: create a synthetic `()` during lowering so we have something to refer to here? + coerce.coerce(self, *expr, &val_ty); + let ctxt = find_breakable(&mut self.breakables, label.as_ref()) + .expect("breakable stack changed during coercion"); + ctxt.coerce = coerce; + ctxt.may_break = true; + } + None => { + self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { + expr: tgt_expr, + is_break: true, + }); + } + } TyKind::Never.intern(Interner) } Expr::Return { expr } => { @@ -794,9 +802,6 @@ impl<'a> InferenceContext<'a> { None => self.table.new_float_var(), }, }, - Expr::MacroStmts { tail, statements } => { - self.infer_block(tgt_expr, statements, *tail, expected) - } Expr::Underscore => { // Underscore expressions may only appear in assignee expressions, // which are handled by `infer_assignee_expr()`, so any underscore @@ -1475,4 +1480,20 @@ impl<'a> InferenceContext<'a> { }, }) } + + fn with_breakable_ctx<T>( + &mut self, + kind: BreakableKind, + ty: Ty, + label: Option<LabelId>, + cb: impl FnOnce(&mut Self) -> T, + ) -> (Option<Ty>, T) { + self.breakables.push({ + let label = label.map(|label| self.body[label].name.clone()); + BreakableContext { kind, may_break: false, coerce: CoerceMany::new(ty), label } + }); + let res = cb(self); + let ctx = self.breakables.pop().expect("breakable stack broken"); + (ctx.may_break.then(|| ctx.coerce.complete()), res) + } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs new file mode 100644 index 00000000000..0c547192ac0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -0,0 +1,173 @@ +//! Type inhabitedness logic. +use std::ops::ControlFlow::{self, Break, Continue}; + +use chalk_ir::{ + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, + DebruijnIndex, +}; +use hir_def::{ + adt::VariantData, attr::Attrs, type_ref::ConstScalar, visibility::Visibility, AdtId, + EnumVariantId, HasModule, Lookup, ModuleId, VariantId, +}; + +use crate::{ + db::HirDatabase, Binders, ConcreteConst, Const, ConstValue, Interner, Substitution, Ty, TyKind, +}; + +/// Checks whether a type is visibly uninhabited from a particular module. +pub(crate) fn is_ty_uninhabited_from(ty: &Ty, target_mod: ModuleId, db: &dyn HirDatabase) -> bool { + let mut uninhabited_from = UninhabitedFrom { target_mod, db }; + let inhabitedness = ty.visit_with(&mut uninhabited_from, DebruijnIndex::INNERMOST); + inhabitedness == BREAK_VISIBLY_UNINHABITED +} + +/// Checks whether a variant is visibly uninhabited from a particular module. +pub(crate) fn is_enum_variant_uninhabited_from( + variant: EnumVariantId, + subst: &Substitution, + target_mod: ModuleId, + db: &dyn HirDatabase, +) -> bool { + let enum_data = db.enum_data(variant.parent); + let vars_attrs = db.variants_attrs(variant.parent); + let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate(); + + let mut uninhabited_from = UninhabitedFrom { target_mod, db }; + let inhabitedness = uninhabited_from.visit_variant( + variant.into(), + &enum_data.variants[variant.local_id].variant_data, + subst, + &vars_attrs[variant.local_id], + is_local, + ); + inhabitedness == BREAK_VISIBLY_UNINHABITED +} + +struct UninhabitedFrom<'a> { + target_mod: ModuleId, + db: &'a dyn HirDatabase, +} + +const CONTINUE_OPAQUELY_INHABITED: ControlFlow<VisiblyUninhabited> = Continue(()); +const BREAK_VISIBLY_UNINHABITED: ControlFlow<VisiblyUninhabited> = Break(VisiblyUninhabited); +#[derive(PartialEq, Eq)] +struct VisiblyUninhabited; + +impl TypeVisitor<Interner> for UninhabitedFrom<'_> { + type BreakTy = VisiblyUninhabited; + + fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = VisiblyUninhabited> { + self + } + + fn visit_ty( + &mut self, + ty: &Ty, + outer_binder: DebruijnIndex, + ) -> ControlFlow<VisiblyUninhabited> { + match ty.kind(Interner) { + TyKind::Adt(adt, subst) => self.visit_adt(adt.0, subst), + TyKind::Never => BREAK_VISIBLY_UNINHABITED, + TyKind::Tuple(..) => ty.super_visit_with(self, outer_binder), + TyKind::Array(item_ty, len) => match try_usize_const(len) { + Some(0) | None => CONTINUE_OPAQUELY_INHABITED, + Some(1..) => item_ty.super_visit_with(self, outer_binder), + }, + + TyKind::Ref(..) | _ => CONTINUE_OPAQUELY_INHABITED, + } + } + + fn interner(&self) -> Interner { + Interner + } +} + +impl UninhabitedFrom<'_> { + fn visit_adt(&mut self, adt: AdtId, subst: &Substitution) -> ControlFlow<VisiblyUninhabited> { + let attrs = self.db.attrs(adt.into()); + let adt_non_exhaustive = attrs.by_key("non_exhaustive").exists(); + let is_local = adt.module(self.db.upcast()).krate() == self.target_mod.krate(); + if adt_non_exhaustive && !is_local { + return CONTINUE_OPAQUELY_INHABITED; + } + + // An ADT is uninhabited iff all its variants uninhabited. + match adt { + // rustc: For now, `union`s are never considered uninhabited. + AdtId::UnionId(_) => CONTINUE_OPAQUELY_INHABITED, + AdtId::StructId(s) => { + let struct_data = self.db.struct_data(s); + self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local) + } + AdtId::EnumId(e) => { + let vars_attrs = self.db.variants_attrs(e); + let enum_data = self.db.enum_data(e); + + for (local_id, enum_var) in enum_data.variants.iter() { + let variant_inhabitedness = self.visit_variant( + EnumVariantId { parent: e, local_id }.into(), + &enum_var.variant_data, + subst, + &vars_attrs[local_id], + is_local, + ); + match variant_inhabitedness { + Break(VisiblyUninhabited) => continue, + Continue(()) => return CONTINUE_OPAQUELY_INHABITED, + } + } + BREAK_VISIBLY_UNINHABITED + } + } + } + + fn visit_variant( + &mut self, + variant: VariantId, + variant_data: &VariantData, + subst: &Substitution, + attrs: &Attrs, + is_local: bool, + ) -> ControlFlow<VisiblyUninhabited> { + let non_exhaustive_field_list = attrs.by_key("non_exhaustive").exists(); + if non_exhaustive_field_list && !is_local { + return CONTINUE_OPAQUELY_INHABITED; + } + + let is_enum = matches!(variant, VariantId::EnumVariantId(..)); + let field_tys = self.db.field_types(variant); + let field_vis = self.db.field_visibilities(variant); + + for (fid, _) in variant_data.fields().iter() { + self.visit_field(field_vis[fid], &field_tys[fid], subst, is_enum)?; + } + CONTINUE_OPAQUELY_INHABITED + } + + fn visit_field( + &mut self, + vis: Visibility, + ty: &Binders<Ty>, + subst: &Substitution, + is_enum: bool, + ) -> ControlFlow<VisiblyUninhabited> { + if is_enum || vis.is_visible_from(self.db.upcast(), self.target_mod) { + let ty = ty.clone().substitute(Interner, subst); + ty.visit_with(self, DebruijnIndex::INNERMOST) + } else { + CONTINUE_OPAQUELY_INHABITED + } + } +} + +fn try_usize_const(c: &Const) -> Option<u128> { + let data = &c.data(Interner); + if data.ty.kind(Interner) != &TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)) { + return None; + } + match data.value { + ConstValue::Concrete(ConcreteConst { interned: ConstScalar::UInt(value) }) => Some(value), + _ => None, + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 5a5d610e360..a82a331d4b8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -14,6 +14,7 @@ mod chalk_db; mod chalk_ext; pub mod consteval; mod infer; +mod inhabitedness; mod interner; mod lower; mod mapping; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 3f6d0844e9c..4a37a794533 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1,8 +1,8 @@ //! Methods for lowering the HIR to types. There are two main cases here: //! //! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a -//! type: The entry point for this is `Ty::from_hir`. -//! - Building the type for an item: This happens through the `type_for_def` query. +//! type: The entry point for this is `TyLoweringContext::lower_ty`. +//! - Building the type for an item: This happens through the `ty` query. //! //! This usually involves resolving names, collecting generic arguments etc. use std::{ @@ -47,7 +47,7 @@ use crate::{ consteval::{intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic}, db::HirDatabase, make_binders, - mapping::ToChalk, + mapping::{from_chalk_trait_id, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::Generics, utils::{all_super_trait_refs, associated_type_by_name_including_super_traits, generics}, @@ -332,7 +332,10 @@ impl<'a> TyLoweringContext<'a> { TypeRef::Macro(macro_call) => { let (mut expander, recursion_start) = { match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) { + // There already is an expander here, this means we are already recursing Ok(expander) => (expander, false), + // No expander was created yet, so we are at the start of the expansion recursion + // and therefore have to create an expander. Err(expander) => ( RefMut::map(expander, |it| { it.insert(Expander::new( @@ -362,9 +365,14 @@ impl<'a> TyLoweringContext<'a> { .exit(self.db.upcast(), mark); Some(ty) } - _ => None, + _ => { + drop(expander); + None + } } }; + + // drop the expander, resetting it to pre-recursion state if recursion_start { *self.expander.borrow_mut() = None; } @@ -974,13 +982,44 @@ impl<'a> TyLoweringContext<'a> { fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty { let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - QuantifiedWhereClauses::from_iter( + let bounds = + bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)); + + let mut auto_traits = SmallVec::<[_; 8]>::new(); + let mut regular_traits = SmallVec::<[_; 2]>::new(); + let mut other_bounds = SmallVec::<[_; 8]>::new(); + for bound in bounds { + if let Some(id) = bound.trait_id() { + if ctx.db.trait_data(from_chalk_trait_id(id)).is_auto { + auto_traits.push(bound); + } else { + regular_traits.push(bound); + } + } else { + other_bounds.push(bound); + } + } + + if regular_traits.len() > 1 { + return None; + } + + auto_traits.sort_unstable_by_key(|b| b.trait_id().unwrap()); + auto_traits.dedup(); + + Some(QuantifiedWhereClauses::from_iter( Interner, - bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), - ) + regular_traits.into_iter().chain(other_bounds).chain(auto_traits), + )) }); - let bounds = crate::make_single_type_binders(bounds); - TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner) + + if let Some(bounds) = bounds { + let bounds = crate::make_single_type_binders(bounds); + TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner) + } else { + // FIXME: report error (additional non-auto traits) + TyKind::Error.intern(Interner) + } } fn lower_impl_trait( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index a1ab6060e79..b3adafaafd3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -193,8 +193,6 @@ fn expr_macro_def_expanded_in_various_places() { !0..6 '1isize': isize !0..6 '1isize': isize !0..6 '1isize': isize - !0..6 '1isize': isize - !0..6 '1isize': isize 39..442 '{ ...!(); }': () 73..94 'spam!(...am!())': {unknown} 100..119 'for _ ...!() {}': () @@ -276,8 +274,6 @@ fn expr_macro_rules_expanded_in_various_places() { !0..6 '1isize': isize !0..6 '1isize': isize !0..6 '1isize': isize - !0..6 '1isize': isize - !0..6 '1isize': isize 53..456 '{ ...!(); }': () 87..108 'spam!(...am!())': {unknown} 114..133 'for _ ...!() {}': () @@ -312,7 +308,6 @@ fn expr_macro_expanded_in_stmts() { } "#, expect![[r#" - !0..8 'leta=();': () !3..4 'a': () !5..7 '()': () 57..84 '{ ...); } }': () @@ -321,7 +316,7 @@ fn expr_macro_expanded_in_stmts() { } #[test] -fn recurisve_macro_expanded_in_stmts() { +fn recursive_macro_expanded_in_stmts() { check_infer( r#" macro_rules! ng { @@ -340,11 +335,6 @@ fn recurisve_macro_expanded_in_stmts() { } "#, expect![[r#" - !0..7 'leta=3;': () - !0..13 'ng!{[leta=3]}': () - !0..13 'ng!{[leta=]3}': () - !0..13 'ng!{[leta]=3}': () - !0..13 'ng!{[let]a=3}': () !3..4 'a': i32 !5..6 '3': i32 196..237 '{ ...= a; }': () @@ -369,8 +359,6 @@ fn recursive_inner_item_macro_rules() { "#, expect![[r#" !0..1 '1': i32 - !0..7 'mac!($)': () - !0..26 'macro_...>{1};}': () 107..143 '{ ...!(); }': () 129..130 'a': i32 "#]], diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index c7895db1afb..23e51a9c16a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -573,7 +573,6 @@ fn issue_6811() { } "#, expect![[r#" - !0..16 'let_a=...t_b=1;': () !3..5 '_a': i32 !6..7 '1': i32 !11..13 '_b': i32 @@ -1679,7 +1678,6 @@ fn main() { #[test] fn trailing_empty_macro() { - cov_mark::check!(empty_macro_in_trailing_position_is_removed); check_no_mismatches( r#" macro_rules! m2 { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 5b08f552109..4ea103e5d9e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -2549,7 +2549,6 @@ impl B for Astruct {} expect![[r#" 569..573 'self': Box<[T], A> 602..634 '{ ... }': Vec<T, A> - 612..628 'unimpl...ted!()': Vec<T, A> 648..761 '{ ...t]); }': () 658..661 'vec': Vec<i32, Global> 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> @@ -3070,3 +3069,17 @@ fn main() { "#, ); } + +#[test] +fn nested_break() { + check_no_mismatches( + r#" +fn func() { + let int = loop { + break 0; + break (break 0); + }; +} + "#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index 0f37970e2b3..e67c27aa2db 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -3833,3 +3833,95 @@ fn test() { "#, ) } + +#[test] +fn dyn_multiple_auto_traits_in_different_order() { + check_no_mismatches( + r#" +auto trait Send {} +auto trait Sync {} + +fn f(t: &(dyn Sync + Send)) {} +fn g(t: &(dyn Send + Sync)) { + f(t); +} + "#, + ); + + check_no_mismatches( + r#" +auto trait Send {} +auto trait Sync {} +trait T {} + +fn f(t: &(dyn T + Send + Sync)) {} +fn g(t: &(dyn Sync + T + Send)) { + f(t); +} + "#, + ); + + check_infer_with_mismatches( + r#" +auto trait Send {} +auto trait Sync {} +trait T1 {} +trait T2 {} + +fn f(t: &(dyn T1 + T2 + Send + Sync)) {} +fn g(t: &(dyn Sync + T2 + T1 + Send)) { + f(t); +} + "#, + expect![[r#" + 68..69 't': &{unknown} + 101..103 '{}': () + 109..110 't': &{unknown} + 142..155 '{ f(t); }': () + 148..149 'f': fn f(&{unknown}) + 148..152 'f(t)': () + 150..151 't': &{unknown} + "#]], + ); + + check_no_mismatches( + r#" +auto trait Send {} +auto trait Sync {} +trait T { + type Proj: Send + Sync; +} + +fn f(t: &(dyn T<Proj = ()> + Send + Sync)) {} +fn g(t: &(dyn Sync + T<Proj = ()> + Send)) { + f(t); +} + "#, + ); +} + +#[test] +fn dyn_duplicate_auto_trait() { + check_no_mismatches( + r#" +auto trait Send {} + +fn f(t: &(dyn Send + Send)) {} +fn g(t: &(dyn Send)) { + f(t); +} + "#, + ); + + check_no_mismatches( + r#" +auto trait Send {} +trait T {} + +fn f(t: &(dyn T + Send + Send)) {} +fn g(t: &(dyn T + Send)) { + f(t); +} + "#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 50374f4b3fe..5edc16d8bce 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -124,6 +124,7 @@ pub struct NoSuchField { #[derive(Debug)] pub struct BreakOutsideOfLoop { pub expr: InFile<AstPtr<ast::Expr>>, + pub is_break: bool, } #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 6dccf2ed20b..e4bb63a8647 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1216,11 +1216,11 @@ impl DefWithBody { let field = source_map.field_syntax(*expr); acc.push(NoSuchField { field }.into()) } - hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => { + &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break } => { let expr = source_map - .expr_syntax(*expr) + .expr_syntax(expr) .expect("break outside of loop in synthetic syntax"); - acc.push(BreakOutsideOfLoop { expr }.into()) + acc.push(BreakOutsideOfLoop { expr, is_break }.into()) } hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { match source_map.expr_syntax(*call_expr) { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index bd35af06e23..342912b678a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -140,11 +140,19 @@ impl SourceAnalyzer { ) -> Option<InFile<ast::Expr>> { let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?; let expanded = db.parse_or_expand(macro_file)?; - - let res = match ast::MacroCall::cast(expanded.clone()) { - Some(call) => self.expand_expr(db, InFile::new(macro_file, call))?, - _ => InFile::new(macro_file, ast::Expr::cast(expanded)?), + let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) { + match stmts.expr()? { + ast::Expr::MacroExpr(mac) => { + self.expand_expr(db, InFile::new(macro_file, mac.macro_call()?))? + } + expr => InFile::new(macro_file, expr), + } + } else if let Some(call) = ast::MacroCall::cast(expanded.clone()) { + self.expand_expr(db, InFile::new(macro_file, call))? + } else { + InFile::new(macro_file, ast::Expr::cast(expanded)?) }; + Some(res) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs new file mode 100644 index 00000000000..54a7f480a4e --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs @@ -0,0 +1,294 @@ +use syntax::ast::{self, AstNode}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: convert_two_arm_bool_match_to_matches_macro +// +// Convert 2-arm match that evaluates to a boolean into the equivalent matches! invocation. +// +// ``` +// fn main() { +// match scrutinee$0 { +// Some(val) if val.cond() => true, +// _ => false, +// } +// } +// ``` +// -> +// ``` +// fn main() { +// matches!(scrutinee, Some(val) if val.cond()) +// } +// ``` +pub(crate) fn convert_two_arm_bool_match_to_matches_macro( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?; + let match_arm_list = match_expr.match_arm_list()?; + let mut arms = match_arm_list.arms(); + let first_arm = arms.next()?; + let second_arm = arms.next()?; + if arms.next().is_some() { + cov_mark::hit!(non_two_arm_match); + return None; + } + let first_arm_expr = first_arm.expr(); + let second_arm_expr = second_arm.expr(); + + let invert_matches = if is_bool_literal_expr(&first_arm_expr, true) + && is_bool_literal_expr(&second_arm_expr, false) + { + false + } else if is_bool_literal_expr(&first_arm_expr, false) + && is_bool_literal_expr(&second_arm_expr, true) + { + true + } else { + cov_mark::hit!(non_invert_bool_literal_arms); + return None; + }; + + let target_range = ctx.sema.original_range(match_expr.syntax()).range; + let expr = match_expr.expr()?; + + acc.add( + AssistId("convert_two_arm_bool_match_to_matches_macro", AssistKind::RefactorRewrite), + "Convert to matches!", + target_range, + |builder| { + let mut arm_str = String::new(); + if let Some(ref pat) = first_arm.pat() { + arm_str += &pat.to_string(); + } + if let Some(ref guard) = first_arm.guard() { + arm_str += &format!(" {}", &guard.to_string()); + } + if invert_matches { + builder.replace(target_range, format!("!matches!({}, {})", expr, arm_str)); + } else { + builder.replace(target_range, format!("matches!({}, {})", expr, arm_str)); + } + }, + ) +} + +fn is_bool_literal_expr(expr: &Option<ast::Expr>, expect_bool: bool) -> bool { + if let Some(ast::Expr::Literal(lit)) = expr { + if let ast::LiteralKind::Bool(b) = lit.kind() { + return b == expect_bool; + } + } + + return false; +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; + + use super::convert_two_arm_bool_match_to_matches_macro; + + #[test] + fn not_applicable_outside_of_range_left() { + check_assist_not_applicable( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + $0 match a { + Some(_val) => true, + _ => false + } +} + "#, + ); + } + + #[test] + fn not_applicable_non_two_arm_match() { + cov_mark::check!(non_two_arm_match); + check_assist_not_applicable( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(3) => true, + Some(4) => true, + _ => false + } +} + "#, + ); + } + + #[test] + fn not_applicable_non_bool_literal_arms() { + cov_mark::check!(non_invert_bool_literal_arms); + check_assist_not_applicable( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(val) => val == 3, + _ => false + } +} + "#, + ); + } + #[test] + fn not_applicable_both_false_arms() { + cov_mark::check!(non_invert_bool_literal_arms); + check_assist_not_applicable( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(val) => false, + _ => false + } +} + "#, + ); + } + + #[test] + fn not_applicable_both_true_arms() { + cov_mark::check!(non_invert_bool_literal_arms); + check_assist_not_applicable( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(val) => true, + _ => true + } +} + "#, + ); + } + + #[test] + fn convert_simple_case() { + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(_val) => true, + _ => false + } +} +"#, + r#" +fn foo(a: Option<u32>) -> bool { + matches!(a, Some(_val)) +} +"#, + ); + } + + #[test] + fn convert_simple_invert_case() { + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(_val) => false, + _ => true + } +} +"#, + r#" +fn foo(a: Option<u32>) -> bool { + !matches!(a, Some(_val)) +} +"#, + ); + } + + #[test] + fn convert_with_guard_case() { + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(val) if val > 3 => true, + _ => false + } +} +"#, + r#" +fn foo(a: Option<u32>) -> bool { + matches!(a, Some(val) if val > 3) +} +"#, + ); + } + + #[test] + fn convert_enum_match_cases() { + check_assist( + convert_two_arm_bool_match_to_matches_macro, + r#" +enum X { A, B } + +fn foo(a: X) -> bool { + match a$0 { + X::A => true, + _ => false + } +} +"#, + r#" +enum X { A, B } + +fn foo(a: X) -> bool { + matches!(a, X::A) +} +"#, + ); + } + + #[test] + fn convert_target_simple() { + check_assist_target( + convert_two_arm_bool_match_to_matches_macro, + r#" +fn foo(a: Option<u32>) -> bool { + match a$0 { + Some(val) => true, + _ => false + } +} +"#, + r#"match a { + Some(val) => true, + _ => false + }"#, + ); + } + + #[test] + fn convert_target_complex() { + check_assist_target( + convert_two_arm_bool_match_to_matches_macro, + r#" +enum E { X, Y } + +fn main() { + match E::X$0 { + E::X => true, + _ => false, + } +} +"#, + "match E::X { + E::X => true, + _ => false, + }", + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index dfb56521264..ddc2052e7aa 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -101,21 +101,22 @@ pub(crate) fn extract_struct_from_enum_variant( }); } - let indent = enum_ast.indent_level(); let generic_params = enum_ast .generic_param_list() .and_then(|known_generics| extract_generic_params(&known_generics, &field_list)); let generics = generic_params.as_ref().map(|generics| generics.clone_for_update()); let def = create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast); + + let enum_ast = variant.parent_enum(); + let indent = enum_ast.indent_level(); def.reindent_to(indent); - let start_offset = &variant.parent_enum().syntax().clone(); - ted::insert_all_raw( - ted::Position::before(start_offset), + ted::insert_all( + ted::Position::before(enum_ast.syntax()), vec![ def.syntax().clone().into(), - make::tokens::whitespace(&format!("\n\n{}", indent)).into(), + make::tokens::whitespace(&format!("\n\n{indent}")).into(), ], ); @@ -227,7 +228,7 @@ fn tag_generics_in_variant(ty: &ast::Type, generics: &mut [(ast::GenericParam, b } fn create_struct_def( - variant_name: ast::Name, + name: ast::Name, variant: &ast::Variant, field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, generics: Option<ast::GenericParamList>, @@ -269,43 +270,27 @@ fn create_struct_def( field_list.into() } }; - field_list.reindent_to(IndentLevel::single()); - let strukt = make::struct_(enum_vis, variant_name, generics, field_list).clone_for_update(); - - // FIXME: Consider making this an actual function somewhere (like in `AttrsOwnerEdit`) after some deliberation - let attrs_and_docs = |node: &SyntaxNode| { - let mut select_next_ws = false; - node.children_with_tokens().filter(move |child| { - let accept = match child.kind() { - ATTR | COMMENT => { - select_next_ws = true; - return true; - } - WHITESPACE if select_next_ws => true, - _ => false, - }; - select_next_ws = false; - - accept - }) - }; + let strukt = make::struct_(enum_vis, name, generics, field_list).clone_for_update(); - // copy attributes & comments from variant - let variant_attrs = attrs_and_docs(variant.syntax()) - .map(|tok| match tok.kind() { - WHITESPACE => make::tokens::single_newline().into(), - _ => tok, - }) - .collect(); - ted::insert_all(ted::Position::first_child_of(strukt.syntax()), variant_attrs); + // take comments from variant + ted::insert_all( + ted::Position::first_child_of(strukt.syntax()), + take_all_comments(variant.syntax()), + ); // copy attributes from enum ted::insert_all( ted::Position::first_child_of(strukt.syntax()), - enum_.attrs().map(|it| it.syntax().clone_for_update().into()).collect(), + enum_ + .attrs() + .flat_map(|it| { + vec![it.syntax().clone_for_update().into(), make::tokens::single_newline().into()] + }) + .collect(), ); + strukt } @@ -346,16 +331,48 @@ fn update_variant(variant: &ast::Variant, generics: Option<ast::GenericParamList }) .unwrap_or_else(|| make::ty(&name.text())); + // change from a record to a tuple field list let tuple_field = make::tuple_field(None, ty); - let replacement = make::variant( - name, - Some(ast::FieldList::TupleFieldList(make::tuple_field_list(iter::once(tuple_field)))), - ) - .clone_for_update(); - ted::replace(variant.syntax(), replacement.syntax()); + let field_list = make::tuple_field_list(iter::once(tuple_field)).clone_for_update(); + ted::replace(variant.field_list()?.syntax(), field_list.syntax()); + + // remove any ws after the name + if let Some(ws) = name + .syntax() + .siblings_with_tokens(syntax::Direction::Next) + .find_map(|tok| tok.into_token().filter(|tok| tok.kind() == WHITESPACE)) + { + ted::remove(SyntaxElement::Token(ws)); + } + Some(()) } +// Note: this also detaches whitespace after comments, +// since `SyntaxNode::splice_children` (and by extension `ted::insert_all_raw`) +// detaches nodes. If we only took the comments, we'd leave behind the old whitespace. +fn take_all_comments(node: &SyntaxNode) -> Vec<SyntaxElement> { + let mut remove_next_ws = false; + node.children_with_tokens() + .filter_map(move |child| match child.kind() { + COMMENT => { + remove_next_ws = true; + child.detach(); + Some(child) + } + WHITESPACE if remove_next_ws => { + remove_next_ws = false; + child.detach(); + Some(make::tokens::single_newline().into()) + } + _ => { + remove_next_ws = false; + None + } + }) + .collect() +} + fn apply_references( insert_use_cfg: InsertUseConfig, segment: ast::PathSegment, @@ -480,10 +497,14 @@ enum En<T> { Var(Var<T>) }"#, fn test_extract_struct_carries_over_attributes() { check_assist( extract_struct_from_enum_variant, - r#"#[derive(Debug)] + r#" +#[derive(Debug)] #[derive(Clone)] enum Enum { Variant{ field: u32$0 } }"#, - r#"#[derive(Debug)]#[derive(Clone)] struct Variant{ field: u32 } + r#" +#[derive(Debug)] +#[derive(Clone)] +struct Variant{ field: u32 } #[derive(Debug)] #[derive(Clone)] @@ -614,7 +635,7 @@ enum A { One(One) }"#, } #[test] - fn test_extract_struct_keep_comments_and_attrs_on_variant_struct() { + fn test_extract_struct_move_struct_variant_comments() { check_assist( extract_struct_from_enum_variant, r#" @@ -631,19 +652,19 @@ enum A { /* comment */ // other /// comment -#[attr] struct One{ a: u32 } enum A { + #[attr] One(One) }"#, ); } #[test] - fn test_extract_struct_keep_comments_and_attrs_on_variant_tuple() { + fn test_extract_struct_move_tuple_variant_comments() { check_assist( extract_struct_from_enum_variant, r#" @@ -658,10 +679,10 @@ enum A { /* comment */ // other /// comment -#[attr] struct One(u32, u32); enum A { + #[attr] One(One) }"#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs new file mode 100644 index 00000000000..7d91be62101 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_or_with_or_else.rs @@ -0,0 +1,364 @@ +use ide_db::{ + assists::{AssistId, AssistKind}, + famous_defs::FamousDefs, +}; +use syntax::{ + ast::{self, make, Expr, HasArgList}, + AstNode, +}; + +use crate::{AssistContext, Assists}; + +// Assist: replace_or_with_or_else +// +// Replace `unwrap_or` with `unwrap_or_else` and `ok_or` with `ok_or_else`. +// +// ``` +// # //- minicore:option +// fn foo() { +// let a = Some(1); +// a.unwra$0p_or(2); +// } +// ``` +// -> +// ``` +// fn foo() { +// let a = Some(1); +// a.unwrap_or_else(|| 2); +// } +// ``` +pub(crate) fn replace_or_with_or_else(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let call: ast::MethodCallExpr = ctx.find_node_at_offset()?; + + let kind = is_option_or_result(call.receiver()?, ctx)?; + + let (name, arg_list) = (call.name_ref()?, call.arg_list()?); + + let mut map_or = false; + + let replace = match &*name.text() { + "unwrap_or" => "unwrap_or_else".to_string(), + "or" => "or_else".to_string(), + "ok_or" if kind == Kind::Option => "ok_or_else".to_string(), + "map_or" => { + map_or = true; + "map_or_else".to_string() + } + _ => return None, + }; + + let arg = match arg_list.args().collect::<Vec<_>>().as_slice() { + [] => make::arg_list(Vec::new()), + [first] => { + let param = into_closure(first); + make::arg_list(vec![param]) + } + [first, second] if map_or => { + let param = into_closure(first); + make::arg_list(vec![param, second.clone()]) + } + _ => return None, + }; + + acc.add( + AssistId("replace_or_with_or_else", AssistKind::RefactorRewrite), + format!("Replace {} with {}", name.text(), replace), + call.syntax().text_range(), + |builder| { + builder.replace(name.syntax().text_range(), replace); + builder.replace_ast(arg_list, arg) + }, + ) +} + +fn into_closure(param: &Expr) -> Expr { + (|| { + if let ast::Expr::CallExpr(call) = param { + if call.arg_list()?.args().count() == 0 { + Some(call.expr()?.clone()) + } else { + None + } + } else { + None + } + })() + .unwrap_or_else(|| make::expr_closure(None, param.clone())) +} + +// Assist: replace_or_else_with_or +// +// Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`. +// +// ``` +// # //- minicore:option +// fn foo() { +// let a = Some(1); +// a.unwra$0p_or_else(|| 2); +// } +// ``` +// -> +// ``` +// fn foo() { +// let a = Some(1); +// a.unwrap_or(2); +// } +// ``` +pub(crate) fn replace_or_else_with_or(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let call: ast::MethodCallExpr = ctx.find_node_at_offset()?; + + let kind = is_option_or_result(call.receiver()?, ctx)?; + + let (name, arg_list) = (call.name_ref()?, call.arg_list()?); + + let mut map_or = false; + let replace = match &*name.text() { + "unwrap_or_else" => "unwrap_or".to_string(), + "or_else" => "or".to_string(), + "ok_or_else" if kind == Kind::Option => "ok_or".to_string(), + "map_or_else" => { + map_or = true; + "map_or".to_string() + } + _ => return None, + }; + + let arg = match arg_list.args().collect::<Vec<_>>().as_slice() { + [] => make::arg_list(Vec::new()), + [first] => { + let param = into_call(first); + make::arg_list(vec![param]) + } + [first, second] if map_or => { + let param = into_call(first); + make::arg_list(vec![param, second.clone()]) + } + _ => return None, + }; + + acc.add( + AssistId("replace_or_else_with_or", AssistKind::RefactorRewrite), + format!("Replace {} with {}", name.text(), replace), + call.syntax().text_range(), + |builder| { + builder.replace(name.syntax().text_range(), replace); + builder.replace_ast(arg_list, arg) + }, + ) +} + +fn into_call(param: &Expr) -> Expr { + (|| { + if let ast::Expr::ClosureExpr(closure) = param { + if closure.param_list()?.params().count() == 0 { + Some(closure.body()?.clone()) + } else { + None + } + } else { + None + } + })() + .unwrap_or_else(|| make::expr_call(param.clone(), make::arg_list(Vec::new()))) +} + +#[derive(PartialEq, Eq)] +enum Kind { + Option, + Result, +} + +fn is_option_or_result(receiver: Expr, ctx: &AssistContext<'_>) -> Option<Kind> { + let ty = ctx.sema.type_of_expr(&receiver)?.adjusted().as_adt()?.as_enum()?; + let option_enum = + FamousDefs(&ctx.sema, ctx.sema.scope(receiver.syntax())?.krate()).core_option_Option(); + + if let Some(option_enum) = option_enum { + if ty == option_enum { + return Some(Kind::Option); + } + } + + let result_enum = + FamousDefs(&ctx.sema, ctx.sema.scope(receiver.syntax())?.krate()).core_result_Result(); + + if let Some(result_enum) = result_enum { + if ty == result_enum { + return Some(Kind::Result); + } + } + + None +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn replace_or_with_or_else_simple() { + check_assist( + replace_or_with_or_else, + r#" +//- minicore: option +fn foo() { + let foo = Some(1); + return foo.unwrap_$0or(2); +} +"#, + r#" +fn foo() { + let foo = Some(1); + return foo.unwrap_or_else(|| 2); +} +"#, + ) + } + + #[test] + fn replace_or_with_or_else_call() { + check_assist( + replace_or_with_or_else, + r#" +//- minicore: option +fn foo() { + let foo = Some(1); + return foo.unwrap_$0or(x()); +} +"#, + r#" +fn foo() { + let foo = Some(1); + return foo.unwrap_or_else(x); +} +"#, + ) + } + + #[test] + fn replace_or_with_or_else_block() { + check_assist( + replace_or_with_or_else, + r#" +//- minicore: option +fn foo() { + let foo = Some(1); + return foo.unwrap_$0or({ + let mut x = bar(); + for i in 0..10 { + x += i; + } + x + }); +} +"#, + r#" +fn foo() { + let foo = Some(1); + return foo.unwrap_or_else(|| { + let mut x = bar(); + for i in 0..10 { + x += i; + } + x + }); +} +"#, + ) + } + + #[test] + fn replace_or_else_with_or_simple() { + check_assist( + replace_or_else_with_or, + r#" +//- minicore: option +fn foo() { + let foo = Some(1); + return foo.unwrap_$0or_else(|| 2); +} +"#, + r#" +fn foo() { + let foo = Some(1); + return foo.unwrap_or(2); +} +"#, + ) + } + + #[test] + fn replace_or_else_with_or_call() { + check_assist( + replace_or_else_with_or, + r#" +//- minicore: option +fn foo() { + let foo = Some(1); + return foo.unwrap_$0or_else(x); +} +"#, + r#" +fn foo() { + let foo = Some(1); + return foo.unwrap_or(x()); +} +"#, + ) + } + + #[test] + fn replace_or_else_with_or_result() { + check_assist( + replace_or_else_with_or, + r#" +//- minicore: result +fn foo() { + let foo = Ok(1); + return foo.unwrap_$0or_else(x); +} +"#, + r#" +fn foo() { + let foo = Ok(1); + return foo.unwrap_or(x()); +} +"#, + ) + } + + #[test] + fn replace_or_else_with_or_map() { + check_assist( + replace_or_else_with_or, + r#" +//- minicore: result +fn foo() { + let foo = Ok("foo"); + return foo.map$0_or_else(|| 42, |v| v.len()); +} +"#, + r#" +fn foo() { + let foo = Ok("foo"); + return foo.map_or(42, |v| v.len()); +} +"#, + ) + } + + #[test] + fn replace_or_else_with_or_not_applicable() { + check_assist_not_applicable( + replace_or_else_with_or, + r#" +fn foo() { + let foo = Ok(1); + return foo.unwrap_$0or_else(x); +} +"#, + ) + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs index 5242f3b5100..521447c26df 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -1,5 +1,6 @@ +use hir::HirDisplay; use syntax::{ - ast::{Expr, GenericArg}, + ast::{Expr, GenericArg, GenericArgList}, ast::{LetStmt, Type::InferType}, AstNode, TextRange, }; @@ -34,21 +35,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( let initializer = let_stmt.initializer()?; - let generic_args = match &initializer { - Expr::MethodCallExpr(ce) => ce.generic_arg_list()?, - Expr::CallExpr(ce) => { - if let Expr::PathExpr(pe) = ce.expr()? { - pe.path()?.segment()?.generic_arg_list()? - } else { - cov_mark::hit!(not_applicable_if_non_path_function_call); - return None; - } - } - _ => { - cov_mark::hit!(not_applicable_if_non_function_call_initializer); - return None; - } - }; + let generic_args = generic_arg_list(&initializer)?; // Find range of ::<_> let colon2 = generic_args.coloncolon_token()?; @@ -65,7 +52,16 @@ pub(crate) fn replace_turbofish_with_explicit_type( // An improvement would be to check that this is correctly part of the return value of the // function call, or sub in the actual return type. - let turbofish_type = &turbofish_args[0]; + let returned_type = match ctx.sema.type_of_expr(&initializer) { + Some(returned_type) if !returned_type.original.contains_unknown() => { + let module = ctx.sema.scope(let_stmt.syntax())?.module(); + returned_type.original.display_source_code(ctx.db(), module.into()).ok()? + } + _ => { + cov_mark::hit!(fallback_to_turbofish_type_if_type_info_not_available); + turbofish_args[0].to_string() + } + }; let initializer_start = initializer.syntax().text_range().start(); if ctx.offset() > turbofish_range.end() || ctx.offset() < initializer_start { @@ -83,7 +79,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( "Replace turbofish with explicit type", TextRange::new(initializer_start, turbofish_range.end()), |builder| { - builder.insert(ident_range.end(), format!(": {}", turbofish_type)); + builder.insert(ident_range.end(), format!(": {}", returned_type)); builder.delete(turbofish_range); }, ); @@ -98,7 +94,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( "Replace `_` with turbofish type", turbofish_range, |builder| { - builder.replace(underscore_range, turbofish_type.to_string()); + builder.replace(underscore_range, returned_type); builder.delete(turbofish_range); }, ); @@ -107,6 +103,26 @@ pub(crate) fn replace_turbofish_with_explicit_type( None } +fn generic_arg_list(expr: &Expr) -> Option<GenericArgList> { + match expr { + Expr::MethodCallExpr(expr) => expr.generic_arg_list(), + Expr::CallExpr(expr) => { + if let Expr::PathExpr(pe) = expr.expr()? { + pe.path()?.segment()?.generic_arg_list() + } else { + cov_mark::hit!(not_applicable_if_non_path_function_call); + return None; + } + } + Expr::AwaitExpr(expr) => generic_arg_list(&expr.expr()?), + Expr::TryExpr(expr) => generic_arg_list(&expr.expr()?), + _ => { + cov_mark::hit!(not_applicable_if_non_function_call_initializer); + None + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -115,6 +131,7 @@ mod tests { #[test] fn replaces_turbofish_for_vec_string() { + cov_mark::check!(fallback_to_turbofish_type_if_type_info_not_available); check_assist( replace_turbofish_with_explicit_type, r#" @@ -135,6 +152,7 @@ fn main() { #[test] fn replaces_method_calls() { // foo.make() is a method call which uses a different expr in the let initializer + cov_mark::check!(fallback_to_turbofish_type_if_type_info_not_available); check_assist( replace_turbofish_with_explicit_type, r#" @@ -240,4 +258,108 @@ fn main() { "#, ); } + + #[test] + fn replaces_turbofish_for_known_type() { + check_assist( + replace_turbofish_with_explicit_type, + r#" +fn make<T>() -> T {} +fn main() { + let a = make$0::<i32>(); +} +"#, + r#" +fn make<T>() -> T {} +fn main() { + let a: i32 = make(); +} +"#, + ); + check_assist( + replace_turbofish_with_explicit_type, + r#" +//- minicore: option +fn make<T>() -> T {} +fn main() { + let a = make$0::<Option<bool>>(); +} +"#, + r#" +fn make<T>() -> T {} +fn main() { + let a: Option<bool> = make(); +} +"#, + ); + } + + #[test] + fn replaces_turbofish_not_same_type() { + check_assist( + replace_turbofish_with_explicit_type, + r#" +//- minicore: option +fn make<T>() -> Option<T> {} +fn main() { + let a = make$0::<u128>(); +} +"#, + r#" +fn make<T>() -> Option<T> {} +fn main() { + let a: Option<u128> = make(); +} +"#, + ); + } + + #[test] + fn replaces_turbofish_for_type_with_defaulted_generic_param() { + check_assist( + replace_turbofish_with_explicit_type, + r#" +struct HasDefault<T, U = i32>(T, U); +fn make<T>() -> HasDefault<T> {} +fn main() { + let a = make$0::<bool>(); +} +"#, + r#" +struct HasDefault<T, U = i32>(T, U); +fn make<T>() -> HasDefault<T> {} +fn main() { + let a: HasDefault<bool> = make(); +} +"#, + ); + } + + #[test] + fn replaces_turbofish_try_await() { + check_assist( + replace_turbofish_with_explicit_type, + r#" +//- minicore: option, future +struct Fut<T>(T); +impl<T> core::future::Future for Fut<T> { + type Output = Option<T>; +} +fn make<T>() -> Fut<T> {} +fn main() { + let a = make$0::<bool>().await?; +} +"#, + r#" +struct Fut<T>(T); +impl<T> core::future::Future for Fut<T> { + type Output = Option<T>; +} +fn make<T>() -> Fut<T> {} +fn main() { + let a: bool = make().await?; +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs new file mode 100644 index 00000000000..9565f0ee6f2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -0,0 +1,293 @@ +use syntax::{ + algo::neighbor, + ast::{self, edit::IndentLevel, make, AstNode}, + ted::{self, Position}, + Direction, SyntaxKind, T, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: unmerge_match_arm +// +// Splits the current match with a `|` pattern into two arms with identical bodies. +// +// ``` +// enum Action { Move { distance: u32 }, Stop } +// +// fn handle(action: Action) { +// match action { +// Action::Move(..) $0| Action::Stop => foo(), +// } +// } +// ``` +// -> +// ``` +// enum Action { Move { distance: u32 }, Stop } +// +// fn handle(action: Action) { +// match action { +// Action::Move(..) => foo(), +// Action::Stop => foo(), +// } +// } +// ``` +pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let pipe_token = ctx.find_token_syntax_at_offset(T![|])?; + let or_pat = ast::OrPat::cast(pipe_token.parent()?)?.clone_for_update(); + let match_arm = ast::MatchArm::cast(or_pat.syntax().parent()?)?; + let match_arm_body = match_arm.expr()?; + + // We don't need to check for leading pipe because it is directly under `MatchArm` + // without `OrPat`. + + let new_parent = match_arm.syntax().parent()?; + let old_parent_range = new_parent.text_range(); + + acc.add( + AssistId("unmerge_match_arm", AssistKind::RefactorRewrite), + "Unmerge match arm", + pipe_token.text_range(), + |edit| { + let pats_after = pipe_token + .siblings_with_tokens(Direction::Next) + .filter_map(|it| ast::Pat::cast(it.into_node()?)); + // FIXME: We should add a leading pipe if the original arm has one. + let new_match_arm = make::match_arm( + pats_after, + match_arm.guard().and_then(|guard| guard.condition()), + match_arm_body, + ) + .clone_for_update(); + + let mut pipe_index = pipe_token.index(); + if pipe_token + .prev_sibling_or_token() + .map_or(false, |it| it.kind() == SyntaxKind::WHITESPACE) + { + pipe_index -= 1; + } + or_pat.syntax().splice_children( + pipe_index..or_pat.syntax().children_with_tokens().count(), + Vec::new(), + ); + + let mut insert_after_old_arm = Vec::new(); + + // A comma can be: + // - After the arm. In this case we always want to insert a comma after the newly + // inserted arm. + // - Missing after the arm, with no arms after. In this case we want to insert a + // comma before the newly inserted arm. It can not be necessary if there arm + // body is a block, but we don't bother to check that. + // - Missing after the arm with arms after, if the arm body is a block. In this case + // we don't want to insert a comma at all. + let has_comma_after = + std::iter::successors(match_arm.syntax().last_child_or_token(), |it| { + it.prev_sibling_or_token() + }) + .map(|it| it.kind()) + .skip_while(|it| it.is_trivia()) + .next() + == Some(T![,]); + let has_arms_after = neighbor(&match_arm, Direction::Next).is_some(); + if !has_comma_after && !has_arms_after { + insert_after_old_arm.push(make::token(T![,]).into()); + } + + let indent = IndentLevel::from_node(match_arm.syntax()); + insert_after_old_arm.push(make::tokens::whitespace(&format!("\n{indent}")).into()); + + insert_after_old_arm.push(new_match_arm.syntax().clone().into()); + + ted::insert_all_raw(Position::after(match_arm.syntax()), insert_after_old_arm); + + if has_comma_after { + ted::insert_raw( + Position::last_child_of(new_match_arm.syntax()), + make::token(T![,]), + ); + } + + edit.replace(old_parent_range, new_parent.to_string()); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn unmerge_match_arm_single_pipe() { + check_assist( + unmerge_match_arm, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + let x = X::A; + let y = match x { + X::A $0| X::B => { 1i32 } + X::C => { 2i32 } + }; +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + let x = X::A; + let y = match x { + X::A => { 1i32 } + X::B => { 1i32 } + X::C => { 2i32 } + }; +} +"#, + ); + } + + #[test] + fn unmerge_match_arm_guard() { + check_assist( + unmerge_match_arm, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + let x = X::A; + let y = match x { + X::A $0| X::B if true => { 1i32 } + _ => { 2i32 } + }; +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + let x = X::A; + let y = match x { + X::A if true => { 1i32 } + X::B if true => { 1i32 } + _ => { 2i32 } + }; +} +"#, + ); + } + + #[test] + fn unmerge_match_arm_leading_pipe() { + check_assist_not_applicable( + unmerge_match_arm, + r#" + +fn main() { + let y = match 0 { + |$0 0 => { 1i32 } + 1 => { 2i32 } + }; +} +"#, + ); + } + + #[test] + fn unmerge_match_arm_multiple_pipes() { + check_assist( + unmerge_match_arm, + r#" +#[derive(Debug)] +enum X { A, B, C, D, E } + +fn main() { + let x = X::A; + let y = match x { + X::A | X::B |$0 X::C | X::D => 1i32, + X::E => 2i32, + }; +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C, D, E } + +fn main() { + let x = X::A; + let y = match x { + X::A | X::B => 1i32, + X::C | X::D => 1i32, + X::E => 2i32, + }; +} +"#, + ); + } + + #[test] + fn unmerge_match_arm_inserts_comma_if_required() { + check_assist( + unmerge_match_arm, + r#" +#[derive(Debug)] +enum X { A, B } + +fn main() { + let x = X::A; + let y = match x { + X::A $0| X::B => 1i32 + }; +} +"#, + r#" +#[derive(Debug)] +enum X { A, B } + +fn main() { + let x = X::A; + let y = match x { + X::A => 1i32, + X::B => 1i32 + }; +} +"#, + ); + } + + #[test] + fn unmerge_match_arm_inserts_comma_if_had_after() { + check_assist( + unmerge_match_arm, + r#" +#[derive(Debug)] +enum X { A, B } + +fn main() { + let x = X::A; + match x { + X::A $0| X::B => {}, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B } + +fn main() { + let x = X::A; + match x { + X::A => {}, + X::B => {}, + } +} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 7fb35143fa2..e52544db5f5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -122,6 +122,7 @@ mod handlers { mod convert_let_else_to_match; mod convert_tuple_struct_to_named_struct; mod convert_to_guarded_return; + mod convert_two_arm_bool_match_to_matches_macro; mod convert_while_to_loop; mod destructure_tuple_binding; mod expand_glob_import; @@ -179,12 +180,14 @@ mod handlers { mod replace_try_expr_with_match; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; + mod replace_or_with_or_else; mod introduce_named_generic; mod replace_let_with_if_let; mod replace_qualified_name_with_use; mod replace_string_with_char; mod replace_turbofish_with_explicit_type; mod split_import; + mod unmerge_match_arm; mod sort_items; mod toggle_ignore; mod unmerge_use; @@ -215,6 +218,7 @@ mod handlers { convert_let_else_to_match::convert_let_else_to_match, convert_to_guarded_return::convert_to_guarded_return, convert_tuple_struct_to_named_struct::convert_tuple_struct_to_named_struct, + convert_two_arm_bool_match_to_matches_macro::convert_two_arm_bool_match_to_matches_macro, convert_while_to_loop::convert_while_to_loop, destructure_tuple_binding::destructure_tuple_binding, expand_glob_import::expand_glob_import, @@ -273,11 +277,14 @@ mod handlers { replace_if_let_with_match::replace_if_let_with_match, replace_if_let_with_match::replace_match_with_if_let, replace_let_with_if_let::replace_let_with_if_let, + replace_or_with_or_else::replace_or_else_with_or, + replace_or_with_or_else::replace_or_with_or_else, replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type, replace_qualified_name_with_use::replace_qualified_name_with_use, sort_items::sort_items, split_import::split_import, toggle_ignore::toggle_ignore, + unmerge_match_arm::unmerge_match_arm, unmerge_use::unmerge_use, unnecessary_async::unnecessary_async, unwrap_block::unwrap_block, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 22319f36134..a8c8622c1c1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -473,6 +473,26 @@ impl Point { } #[test] +fn doctest_convert_two_arm_bool_match_to_matches_macro() { + check_doc_test( + "convert_two_arm_bool_match_to_matches_macro", + r#####" +fn main() { + match scrutinee$0 { + Some(val) if val.cond() => true, + _ => false, + } +} +"#####, + r#####" +fn main() { + matches!(scrutinee, Some(val) if val.cond()) +} +"#####, + ) +} + +#[test] fn doctest_convert_while_to_loop() { check_doc_test( "convert_while_to_loop", @@ -2010,6 +2030,46 @@ fn handle(action: Action) { } #[test] +fn doctest_replace_or_else_with_or() { + check_doc_test( + "replace_or_else_with_or", + r#####" +//- minicore:option +fn foo() { + let a = Some(1); + a.unwra$0p_or_else(|| 2); +} +"#####, + r#####" +fn foo() { + let a = Some(1); + a.unwrap_or(2); +} +"#####, + ) +} + +#[test] +fn doctest_replace_or_with_or_else() { + check_doc_test( + "replace_or_with_or_else", + r#####" +//- minicore:option +fn foo() { + let a = Some(1); + a.unwra$0p_or(2); +} +"#####, + r#####" +fn foo() { + let a = Some(1); + a.unwrap_or_else(|| 2); +} +"#####, + ) +} + +#[test] fn doctest_replace_qualified_name_with_use() { check_doc_test( "replace_qualified_name_with_use", @@ -2208,6 +2268,32 @@ fn arithmetics { } #[test] +fn doctest_unmerge_match_arm() { + check_doc_test( + "unmerge_match_arm", + r#####" +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move(..) $0| Action::Stop => foo(), + } +} +"#####, + r#####" +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move(..) => foo(), + Action::Stop => foo(), + } +} +"#####, + ) +} + +#[test] fn doctest_unmerge_use() { check_doc_test( "unmerge_use", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 4d66af9e8d5..588b52cc1ee 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -282,14 +282,26 @@ pub(crate) fn complete_expr_path( } } - if let Some(ty) = innermost_ret_ty { + if let Some(ret_ty) = innermost_ret_ty { add_keyword( "return", - match (in_block_expr, ty.is_unit()) { - (true, true) => "return ;", - (true, false) => "return;", - (false, true) => "return $0", - (false, false) => "return", + match (ret_ty.is_unit(), in_block_expr) { + (true, true) => { + cov_mark::hit!(return_unit_block); + "return;" + } + (true, false) => { + cov_mark::hit!(return_unit_no_block); + "return" + } + (false, true) => { + cov_mark::hit!(return_value_block); + "return $0;" + } + (false, false) => { + cov_mark::hit!(return_value_no_block); + "return $0" + } }, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 925081ebf66..38e24ebc732 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1,7 +1,7 @@ //! Completion tests for expressions. use expect_test::{expect, Expect}; -use crate::tests::{completion_list, BASE_ITEMS_FIXTURE}; +use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE}; fn check(ra_fixture: &str, expect: Expect) { let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture)); @@ -670,3 +670,39 @@ fn main() { "#]], ); } + +#[test] +fn return_unit_block() { + cov_mark::check!(return_unit_block); + check_edit("return", r#"fn f() { if true { $0 } }"#, r#"fn f() { if true { return; } }"#); +} + +#[test] +fn return_unit_no_block() { + cov_mark::check!(return_unit_no_block); + check_edit( + "return", + r#"fn f() { match () { () => $0 } }"#, + r#"fn f() { match () { () => return } }"#, + ); +} + +#[test] +fn return_value_block() { + cov_mark::check!(return_value_block); + check_edit( + "return", + r#"fn f() -> i32 { if true { $0 } }"#, + r#"fn f() -> i32 { if true { return $0; } }"#, + ); +} + +#[test] +fn return_value_no_block() { + cov_mark::check!(return_value_no_block); + check_edit( + "return", + r#"fn f() -> i32 { match () { () => $0 } }"#, + r#"fn f() -> i32 { match () { () => return $0 } }"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index 84bde4d44db..b890e2b58df 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -315,7 +315,6 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) { | ast::Expr::IndexExpr(_) | ast::Expr::Literal(_) | ast::Expr::MacroExpr(_) - | ast::Expr::MacroStmts(_) | ast::Expr::MethodCallExpr(_) | ast::Expr::ParenExpr(_) | ast::Expr::PathExpr(_) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs index d12594a4ce5..0c92e706b39 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs @@ -7,9 +7,10 @@ pub(crate) fn break_outside_of_loop( ctx: &DiagnosticsContext<'_>, d: &hir::BreakOutsideOfLoop, ) -> Diagnostic { + let construct = if d.is_break { "break" } else { "continue" }; Diagnostic::new( "break-outside-of-loop", - "break outside of loop", + format!("{construct} outside of loop"), ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range, ) } @@ -19,11 +20,122 @@ mod tests { use crate::tests::check_diagnostics; #[test] - fn break_outside_of_loop() { + fn outside_of_loop() { check_diagnostics( r#" -fn foo() { break; } - //^^^^^ error: break outside of loop +fn foo() { + break; + //^^^^^ error: break outside of loop + break 'a; + //^^^^^^^^ error: break outside of loop + continue; + //^^^^^^^^ error: continue outside of loop + continue 'a; + //^^^^^^^^^^^ error: continue outside of loop +} +"#, + ); + } + + #[test] + fn try_blocks_are_borders() { + check_diagnostics( + r#" +fn foo() { + 'a: loop { + try { + break; + //^^^^^ error: break outside of loop + break 'a; + //^^^^^^^^ error: break outside of loop + continue; + //^^^^^^^^ error: continue outside of loop + continue 'a; + //^^^^^^^^^^^ error: continue outside of loop + }; + } +} +"#, + ); + } + + #[test] + fn async_blocks_are_borders() { + check_diagnostics( + r#" +fn foo() { + 'a: loop { + try { + break; + //^^^^^ error: break outside of loop + break 'a; + //^^^^^^^^ error: break outside of loop + continue; + //^^^^^^^^ error: continue outside of loop + continue 'a; + //^^^^^^^^^^^ error: continue outside of loop + }; + } +} +"#, + ); + } + + #[test] + fn closures_are_borders() { + check_diagnostics( + r#" +fn foo() { + 'a: loop { + try { + break; + //^^^^^ error: break outside of loop + break 'a; + //^^^^^^^^ error: break outside of loop + continue; + //^^^^^^^^ error: continue outside of loop + continue 'a; + //^^^^^^^^^^^ error: continue outside of loop + }; + } +} +"#, + ); + } + + #[test] + fn blocks_pass_through() { + check_diagnostics( + r#" +fn foo() { + 'a: loop { + { + break; + break 'a; + continue; + continue 'a; + } + } +} +"#, + ); + } + + #[test] + fn label_blocks() { + check_diagnostics( + r#" +fn foo() { + 'a: { + break; + //^^^^^ error: break outside of loop + break 'a; + continue; + //^^^^^^^^ error: continue outside of loop + continue 'a; + //^^^^^^^^^^^ error: continue outside of loop + } +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 5fcaf405b14..c24430ce604 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -947,6 +947,50 @@ fn f() { ); } + mod rust_unstable { + use super::*; + + #[test] + fn rfc_1872_exhaustive_patterns() { + check_diagnostics_no_bails( + r" +//- minicore: option, result +#![feature(exhaustive_patterns)] +enum Void {} +fn test() { + match None::<!> { None => () } + match Result::<u8, !>::Ok(2) { Ok(_) => () } + match Result::<u8, Void>::Ok(2) { Ok(_) => () } + match (2, loop {}) {} + match Result::<!, !>::Ok(loop {}) {} + match (&loop {}) {} // https://github.com/rust-lang/rust/issues/50642#issuecomment-388234919 + // ^^^^^^^^^^ error: missing match arm: type `&!` is non-empty +}", + ); + } + + #[test] + fn rfc_1872_private_uninhabitedness() { + check_diagnostics_no_bails( + r" +//- minicore: option +//- /lib.rs crate:lib +#![feature(exhaustive_patterns)] +pub struct PrivatelyUninhabited { private_field: Void } +enum Void {} +fn test_local(x: Option<PrivatelyUninhabited>) { + match x {} +} // ^ error: missing match arm: `None` not covered +//- /main.rs crate:main deps:lib +#![feature(exhaustive_patterns)] +fn test(x: Option<lib::PrivatelyUninhabited>) { + match x {} + // ^ error: missing match arm: `None` and `Some(_)` not covered +}", + ); + } + } + mod false_negatives { //! The implementation of match checking here is a work in progress. As we roll this out, we //! prefer false negatives to false positives (ideally there would be no false positives). This diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index ed19784d1fa..e9034daefa8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -1910,7 +1910,7 @@ impl<T> Vec<T> { pub struct Box<T> {} trait Display {} -trait Sync {} +auto trait Sync {} fn main() { // The block expression wrapping disables the constructor hint hiding logic diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs index 8de5d33a193..5dc9c6c82a1 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs @@ -118,6 +118,11 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) { match mode { Mode::Use => {} Mode::Type => { + // test typepathfn_with_coloncolon + // type F = Start::(Middle) -> (Middle)::End; + if p.at(T![::]) && p.nth_at(2, T!['(']) { + p.bump(T![::]); + } // test path_fn_trait_args // type F = Box<Fn(i32) -> ()>; if p.at(T!['(']) { diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index 628fa745e75..c84f45f1f8e 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -262,33 +262,117 @@ pub enum SyntaxKind { use self::SyntaxKind::*; impl SyntaxKind { pub fn is_keyword(self) -> bool { - match self { - AS_KW | ASYNC_KW | AWAIT_KW | BOX_KW | BREAK_KW | CONST_KW | CONTINUE_KW | CRATE_KW - | DYN_KW | ELSE_KW | ENUM_KW | EXTERN_KW | FALSE_KW | FN_KW | FOR_KW | IF_KW - | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW - | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | SELF_TYPE_KW | STATIC_KW - | STRUCT_KW | SUPER_KW | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW - | WHERE_KW | WHILE_KW | YIELD_KW | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW - | RAW_KW | MACRO_RULES_KW => true, - _ => false, - } + matches!( + self, + AS_KW + | ASYNC_KW + | AWAIT_KW + | BOX_KW + | BREAK_KW + | CONST_KW + | CONTINUE_KW + | CRATE_KW + | DYN_KW + | ELSE_KW + | ENUM_KW + | EXTERN_KW + | FALSE_KW + | FN_KW + | FOR_KW + | IF_KW + | IMPL_KW + | IN_KW + | LET_KW + | LOOP_KW + | MACRO_KW + | MATCH_KW + | MOD_KW + | MOVE_KW + | MUT_KW + | PUB_KW + | REF_KW + | RETURN_KW + | SELF_KW + | SELF_TYPE_KW + | STATIC_KW + | STRUCT_KW + | SUPER_KW + | TRAIT_KW + | TRUE_KW + | TRY_KW + | TYPE_KW + | UNSAFE_KW + | USE_KW + | WHERE_KW + | WHILE_KW + | YIELD_KW + | AUTO_KW + | DEFAULT_KW + | EXISTENTIAL_KW + | UNION_KW + | RAW_KW + | MACRO_RULES_KW + ) } pub fn is_punct(self) -> bool { - match self { - SEMICOLON | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK - | L_ANGLE | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS - | STAR | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOT2 | DOT3 | DOT2EQ | COLON - | COLON2 | EQ | EQ2 | FAT_ARROW | BANG | NEQ | MINUS | THIN_ARROW | LTEQ | GTEQ - | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ | PERCENTEQ | AMP2 - | PIPE2 | SHL | SHR | SHLEQ | SHREQ => true, - _ => false, - } + matches!( + self, + SEMICOLON + | COMMA + | L_PAREN + | R_PAREN + | L_CURLY + | R_CURLY + | L_BRACK + | R_BRACK + | L_ANGLE + | R_ANGLE + | AT + | POUND + | TILDE + | QUESTION + | DOLLAR + | AMP + | PIPE + | PLUS + | STAR + | SLASH + | CARET + | PERCENT + | UNDERSCORE + | DOT + | DOT2 + | DOT3 + | DOT2EQ + | COLON + | COLON2 + | EQ + | EQ2 + | FAT_ARROW + | BANG + | NEQ + | MINUS + | THIN_ARROW + | LTEQ + | GTEQ + | PLUSEQ + | MINUSEQ + | PIPEEQ + | AMPEQ + | CARETEQ + | SLASHEQ + | STAREQ + | PERCENTEQ + | AMP2 + | PIPE2 + | SHL + | SHR + | SHLEQ + | SHREQ + ) } pub fn is_literal(self) -> bool { - match self { - INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | BYTE_STRING => true, - _ => false, - } + matches!(self, INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | BYTE_STRING) } pub fn from_keyword(ident: &str) -> Option<SyntaxKind> { let kw = match ident { diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast new file mode 100644 index 00000000000..b47a5a5c147 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast @@ -0,0 +1,43 @@ +SOURCE_FILE + TYPE_ALIAS + TYPE_KW "type" + WHITESPACE " " + NAME + IDENT "F" + WHITESPACE " " + EQ "=" + WHITESPACE " " + PATH_TYPE + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "Start" + COLON2 "::" + PARAM_LIST + L_PAREN "(" + PARAM + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Middle" + R_PAREN ")" + WHITESPACE " " + RET_TYPE + THIN_ARROW "->" + WHITESPACE " " + PAREN_TYPE + L_PAREN "(" + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Middle" + R_PAREN ")" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "End" + SEMICOLON ";" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs new file mode 100644 index 00000000000..8efd93a7ff6 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs @@ -0,0 +1 @@ +type F = Start::(Middle) -> (Middle)::End; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 706e1742dff..92df4d70fd9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -116,6 +116,7 @@ pub(crate) struct GlobalStateSnapshot { pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, vfs: Arc<RwLock<(vfs::Vfs, NoHashHashMap<FileId, LineEndings>)>>, pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, + pub(crate) proc_macros_loaded: bool, } impl std::panic::UnwindSafe for GlobalStateSnapshot {} @@ -256,6 +257,7 @@ impl GlobalState { check_fixes: Arc::clone(&self.diagnostics.check_fixes), mem_docs: self.mem_docs.clone(), semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache), + proc_macros_loaded: !self.fetch_build_data_queue.last_op_result().0.is_empty(), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs index d89f0f5a3cf..d9b669afbe8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs @@ -1504,7 +1504,11 @@ pub(crate) fn handle_semantic_tokens_full( let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; - let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?; + let mut highlight_config = snap.config.highlighting_config(); + // Avoid flashing a bunch of unresolved references when the proc-macro servers haven't been spawned yet. + highlight_config.syntactic_name_ref_highlighting = !snap.proc_macros_loaded; + + let highlights = snap.analysis.highlight(highlight_config, file_id)?; let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); // Unconditionally cache the tokens @@ -1523,7 +1527,11 @@ pub(crate) fn handle_semantic_tokens_full_delta( let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; - let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?; + let mut highlight_config = snap.config.highlighting_config(); + // Avoid flashing a bunch of unresolved references when the proc-macro servers haven't been spawned yet. + highlight_config.syntactic_name_ref_highlighting = !snap.proc_macros_loaded; + + let highlights = snap.analysis.highlight(highlight_config, file_id)?; let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); let mut cache = snap.semantic_tokens_cache.lock(); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index ceb2a6d703d..f23bbca6387 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -347,8 +347,8 @@ impl GlobalState { error }) }) - .collect(); - } + .collect() + }; } let watch = match files_config.watcher { diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 62aa4783994..89479543545 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -343,7 +343,6 @@ Expr = | Literal | LoopExpr | MacroExpr -| MacroStmts | MatchExpr | MethodCallExpr | ParenExpr diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 63309a15521..449402e5f5b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -1526,7 +1526,6 @@ pub enum Expr { Literal(Literal), LoopExpr(LoopExpr), MacroExpr(MacroExpr), - MacroStmts(MacroStmts), MatchExpr(MatchExpr), MethodCallExpr(MethodCallExpr), ParenExpr(ParenExpr), @@ -3169,10 +3168,7 @@ impl From<ConstArg> for GenericArg { } impl AstNode for GenericArg { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true, - _ => false, - } + matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3237,12 +3233,23 @@ impl From<TupleType> for Type { } impl AstNode for Type { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE - | MACRO_TYPE | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE - | SLICE_TYPE | TUPLE_TYPE => true, - _ => false, - } + matches!( + kind, + ARRAY_TYPE + | DYN_TRAIT_TYPE + | FN_PTR_TYPE + | FOR_TYPE + | IMPL_TRAIT_TYPE + | INFER_TYPE + | MACRO_TYPE + | NEVER_TYPE + | PAREN_TYPE + | PATH_TYPE + | PTR_TYPE + | REF_TYPE + | SLICE_TYPE + | TUPLE_TYPE + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3334,9 +3341,6 @@ impl From<LoopExpr> for Expr { impl From<MacroExpr> for Expr { fn from(node: MacroExpr) -> Expr { Expr::MacroExpr(node) } } -impl From<MacroStmts> for Expr { - fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) } -} impl From<MatchExpr> for Expr { fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } } @@ -3384,15 +3388,41 @@ impl From<UnderscoreExpr> for Expr { } impl AstNode for Expr { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR - | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR - | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_EXPR | MACRO_STMTS | MATCH_EXPR - | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR - | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR - | YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true, - _ => false, - } + matches!( + kind, + ARRAY_EXPR + | AWAIT_EXPR + | BIN_EXPR + | BLOCK_EXPR + | BOX_EXPR + | BREAK_EXPR + | CALL_EXPR + | CAST_EXPR + | CLOSURE_EXPR + | CONTINUE_EXPR + | FIELD_EXPR + | FOR_EXPR + | IF_EXPR + | INDEX_EXPR + | LITERAL + | LOOP_EXPR + | MACRO_EXPR + | MATCH_EXPR + | METHOD_CALL_EXPR + | PAREN_EXPR + | PATH_EXPR + | PREFIX_EXPR + | RANGE_EXPR + | RECORD_EXPR + | REF_EXPR + | RETURN_EXPR + | TRY_EXPR + | TUPLE_EXPR + | WHILE_EXPR + | YIELD_EXPR + | LET_EXPR + | UNDERSCORE_EXPR + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3413,7 +3443,6 @@ impl AstNode for Expr { LITERAL => Expr::Literal(Literal { syntax }), LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }), - MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }), MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), @@ -3452,7 +3481,6 @@ impl AstNode for Expr { Expr::Literal(it) => &it.syntax, Expr::LoopExpr(it) => &it.syntax, Expr::MacroExpr(it) => &it.syntax, - Expr::MacroStmts(it) => &it.syntax, Expr::MatchExpr(it) => &it.syntax, Expr::MethodCallExpr(it) => &it.syntax, Expr::ParenExpr(it) => &it.syntax, @@ -3521,11 +3549,25 @@ impl From<Use> for Item { } impl AstNode for Item { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES - | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, - _ => false, - } + matches!( + kind, + CONST + | ENUM + | EXTERN_BLOCK + | EXTERN_CRATE + | FN + | IMPL + | MACRO_CALL + | MACRO_RULES + | MACRO_DEF + | MODULE + | STATIC + | STRUCT + | TRAIT + | TYPE_ALIAS + | UNION + | USE + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3629,12 +3671,25 @@ impl From<ConstBlockPat> for Pat { } impl AstNode for Pat { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT - | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT - | TUPLE_PAT | TUPLE_STRUCT_PAT | CONST_BLOCK_PAT => true, - _ => false, - } + matches!( + kind, + IDENT_PAT + | BOX_PAT + | REST_PAT + | LITERAL_PAT + | MACRO_PAT + | OR_PAT + | PAREN_PAT + | PATH_PAT + | WILDCARD_PAT + | RANGE_PAT + | RECORD_PAT + | REF_PAT + | SLICE_PAT + | TUPLE_PAT + | TUPLE_STRUCT_PAT + | CONST_BLOCK_PAT + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3686,12 +3741,7 @@ impl From<TupleFieldList> for FieldList { fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) } } impl AstNode for FieldList { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - RECORD_FIELD_LIST | TUPLE_FIELD_LIST => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, RECORD_FIELD_LIST | TUPLE_FIELD_LIST) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }), @@ -3717,12 +3767,7 @@ impl From<Union> for Adt { fn from(node: Union) -> Adt { Adt::Union(node) } } impl AstNode for Adt { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - ENUM | STRUCT | UNION => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ENUM | STRUCT | UNION) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { ENUM => Adt::Enum(Enum { syntax }), @@ -3753,12 +3798,7 @@ impl From<TypeAlias> for AssocItem { fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) } } impl AstNode for AssocItem { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CONST | FN | MACRO_CALL | TYPE_ALIAS => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CONST | FN | MACRO_CALL | TYPE_ALIAS) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { CONST => AssocItem::Const(Const { syntax }), @@ -3791,12 +3831,7 @@ impl From<TypeAlias> for ExternItem { fn from(node: TypeAlias) -> ExternItem { ExternItem::TypeAlias(node) } } impl AstNode for ExternItem { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - FN | MACRO_CALL | STATIC | TYPE_ALIAS => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, FN | MACRO_CALL | STATIC | TYPE_ALIAS) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { FN => ExternItem::Fn(Fn { syntax }), @@ -3827,10 +3862,7 @@ impl From<TypeParam> for GenericParam { } impl AstNode for GenericParam { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM => true, - _ => false, - } + matches!(kind, CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -3856,12 +3888,7 @@ impl AnyHasArgList { } } impl AstNode for AnyHasArgList { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CALL_EXPR | METHOD_CALL_EXPR => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CALL_EXPR | METHOD_CALL_EXPR) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasArgList { syntax }) } @@ -3875,76 +3902,76 @@ impl AnyHasAttrs { } impl AstNode for AnyHasAttrs { fn can_cast(kind: SyntaxKind) -> bool { - match kind { + matches!( + kind, MACRO_CALL - | SOURCE_FILE - | CONST - | ENUM - | EXTERN_BLOCK - | EXTERN_CRATE - | FN - | IMPL - | MACRO_RULES - | MACRO_DEF - | MODULE - | STATIC - | STRUCT - | TRAIT - | TYPE_ALIAS - | UNION - | USE - | ITEM_LIST - | BLOCK_EXPR - | SELF_PARAM - | PARAM - | RECORD_FIELD - | TUPLE_FIELD - | VARIANT - | ASSOC_ITEM_LIST - | EXTERN_ITEM_LIST - | CONST_PARAM - | LIFETIME_PARAM - | TYPE_PARAM - | LET_STMT - | ARRAY_EXPR - | AWAIT_EXPR - | BIN_EXPR - | BOX_EXPR - | BREAK_EXPR - | CALL_EXPR - | CAST_EXPR - | CLOSURE_EXPR - | CONTINUE_EXPR - | FIELD_EXPR - | FOR_EXPR - | IF_EXPR - | INDEX_EXPR - | LITERAL - | LOOP_EXPR - | MATCH_EXPR - | METHOD_CALL_EXPR - | PAREN_EXPR - | PATH_EXPR - | PREFIX_EXPR - | RANGE_EXPR - | REF_EXPR - | RETURN_EXPR - | TRY_EXPR - | TUPLE_EXPR - | WHILE_EXPR - | YIELD_EXPR - | LET_EXPR - | UNDERSCORE_EXPR - | STMT_LIST - | RECORD_EXPR_FIELD_LIST - | RECORD_EXPR_FIELD - | MATCH_ARM_LIST - | MATCH_ARM - | IDENT_PAT - | REST_PAT - | RECORD_PAT_FIELD => true, - _ => false, - } + | SOURCE_FILE + | CONST + | ENUM + | EXTERN_BLOCK + | EXTERN_CRATE + | FN + | IMPL + | MACRO_RULES + | MACRO_DEF + | MODULE + | STATIC + | STRUCT + | TRAIT + | TYPE_ALIAS + | UNION + | USE + | ITEM_LIST + | BLOCK_EXPR + | SELF_PARAM + | PARAM + | RECORD_FIELD + | TUPLE_FIELD + | VARIANT + | ASSOC_ITEM_LIST + | EXTERN_ITEM_LIST + | CONST_PARAM + | LIFETIME_PARAM + | TYPE_PARAM + | LET_STMT + | ARRAY_EXPR + | AWAIT_EXPR + | BIN_EXPR + | BOX_EXPR + | BREAK_EXPR + | CALL_EXPR + | CAST_EXPR + | CLOSURE_EXPR + | CONTINUE_EXPR + | FIELD_EXPR + | FOR_EXPR + | IF_EXPR + | INDEX_EXPR + | LITERAL + | LOOP_EXPR + | MATCH_EXPR + | METHOD_CALL_EXPR + | PAREN_EXPR + | PATH_EXPR + | PREFIX_EXPR + | RANGE_EXPR + | REF_EXPR + | RETURN_EXPR + | TRY_EXPR + | TUPLE_EXPR + | WHILE_EXPR + | YIELD_EXPR + | LET_EXPR + | UNDERSCORE_EXPR + | STMT_LIST + | RECORD_EXPR_FIELD_LIST + | RECORD_EXPR_FIELD + | MATCH_ARM_LIST + | MATCH_ARM + | IDENT_PAT + | REST_PAT + | RECORD_PAT_FIELD + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasAttrs { syntax }) @@ -3959,12 +3986,29 @@ impl AnyHasDocComments { } impl AstNode for AnyHasDocComments { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - MACRO_CALL | SOURCE_FILE | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL - | MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION - | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => true, - _ => false, - } + matches!( + kind, + MACRO_CALL + | SOURCE_FILE + | CONST + | ENUM + | EXTERN_BLOCK + | EXTERN_CRATE + | FN + | IMPL + | MACRO_RULES + | MACRO_DEF + | MODULE + | STATIC + | STRUCT + | TRAIT + | TYPE_ALIAS + | UNION + | USE + | RECORD_FIELD + | TUPLE_FIELD + | VARIANT + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasDocComments { syntax }) @@ -3979,10 +4023,7 @@ impl AnyHasGenericParams { } impl AstNode for AnyHasGenericParams { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION => true, - _ => false, - } + matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasGenericParams { syntax }) @@ -3996,12 +4037,7 @@ impl AnyHasLoopBody { } } impl AstNode for AnyHasLoopBody { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - FOR_EXPR | LOOP_EXPR | WHILE_EXPR => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, FOR_EXPR | LOOP_EXPR | WHILE_EXPR) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasLoopBody { syntax }) } @@ -4014,12 +4050,7 @@ impl AnyHasModuleItem { } } impl AstNode for AnyHasModuleItem { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, MACRO_ITEMS | SOURCE_FILE | ITEM_LIST) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasModuleItem { syntax }) } @@ -4033,12 +4064,27 @@ impl AnyHasName { } impl AstNode for AnyHasName { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CONST | ENUM | FN | MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT - | TYPE_ALIAS | UNION | RENAME | SELF_PARAM | RECORD_FIELD | VARIANT | CONST_PARAM - | TYPE_PARAM | IDENT_PAT => true, - _ => false, - } + matches!( + kind, + CONST + | ENUM + | FN + | MACRO_RULES + | MACRO_DEF + | MODULE + | STATIC + | STRUCT + | TRAIT + | TYPE_ALIAS + | UNION + | RENAME + | SELF_PARAM + | RECORD_FIELD + | VARIANT + | CONST_PARAM + | TYPE_PARAM + | IDENT_PAT + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasName { syntax }) @@ -4053,10 +4099,10 @@ impl AnyHasTypeBounds { } impl AstNode for AnyHasTypeBounds { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED => true, - _ => false, - } + matches!( + kind, + ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasTypeBounds { syntax }) @@ -4071,13 +4117,26 @@ impl AnyHasVisibility { } impl AstNode for AnyHasVisibility { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - CONST | ENUM | EXTERN_CRATE | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC - | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => { - true - } - _ => false, - } + matches!( + kind, + CONST + | ENUM + | EXTERN_CRATE + | FN + | IMPL + | MACRO_RULES + | MACRO_DEF + | MODULE + | STATIC + | STRUCT + | TRAIT + | TYPE_ALIAS + | UNION + | USE + | RECORD_FIELD + | TUPLE_FIELD + | VARIANT + ) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| AnyHasVisibility { syntax }) diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 037de876d45..83f8bbac588 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -25,7 +25,7 @@ pub mod ext { return from_text(&name.text()); fn from_text(text: &str) -> ast::IdentPat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } pub fn ident_path(ident: &str) -> ast::Path { @@ -60,10 +60,10 @@ pub mod ext { expr_from_text("todo!()") } pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr { - expr_from_text(&format!("{}::default()", ty)) + expr_from_text(&format!("{ty}::default()")) } pub fn expr_ty_new(ty: &ast::Type) -> ast::Expr { - expr_from_text(&format!("{}::new()", ty)) + expr_from_text(&format!("{ty}::new()")) } pub fn zero_number() -> ast::Expr { @@ -92,18 +92,20 @@ pub mod ext { ty_path(ident_path("bool")) } pub fn ty_option(t: ast::Type) -> ast::Type { - ty_from_text(&format!("Option<{}>", t)) + ty_from_text(&format!("Option<{t}>")) } pub fn ty_result(t: ast::Type, e: ast::Type) -> ast::Type { - ty_from_text(&format!("Result<{}, {}>", t, e)) + ty_from_text(&format!("Result<{t}, {e}>")) } } -pub fn name(text: &str) -> ast::Name { - ast_from_text(&format!("mod {}{};", raw_ident_esc(text), text)) +pub fn name(name: &str) -> ast::Name { + let raw_escape = raw_ident_esc(name); + ast_from_text(&format!("mod {raw_escape}{name};")) } -pub fn name_ref(text: &str) -> ast::NameRef { - ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text)) +pub fn name_ref(name_ref: &str) -> ast::NameRef { + let raw_escape = raw_ident_esc(name_ref); + ast_from_text(&format!("fn f() {{ {raw_escape}{name_ref}; }}")) } fn raw_ident_esc(ident: &str) -> &'static str { let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some(); @@ -118,10 +120,10 @@ pub fn lifetime(text: &str) -> ast::Lifetime { let mut text = text; let tmp; if never!(!text.starts_with('\'')) { - tmp = format!("'{}", text); + tmp = format!("'{text}"); text = &tmp; } - ast_from_text(&format!("fn f<{}>() {{ }}", text)) + ast_from_text(&format!("fn f<{text}>() {{ }}")) } // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la @@ -142,16 +144,16 @@ pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { contents.push(','); } - ty_from_text(&format!("({})", contents)) + ty_from_text(&format!("({contents})")) } pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type { - ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) }) + ty_from_text(&if exclusive { format!("&mut {target}") } else { format!("&{target}") }) } pub fn ty_path(path: ast::Path) -> ast::Type { ty_from_text(&path.to_string()) } fn ty_from_text(text: &str) -> ast::Type { - ast_from_text(&format!("type _T = {};", text)) + ast_from_text(&format!("type _T = {text};")) } pub fn assoc_item_list() -> ast::AssocItemList { @@ -171,7 +173,7 @@ pub fn impl_( Some(params) => params.to_string(), None => String::new(), }; - ast_from_text(&format!("impl{} {}{} {{}}", params, ty, ty_params)) + ast_from_text(&format!("impl{params} {ty}{ty_params} {{}}")) } pub fn impl_trait( @@ -180,7 +182,7 @@ pub fn impl_trait( ty_params: Option<ast::GenericParamList>, ) -> ast::Impl { let ty_params = ty_params.map_or_else(String::new, |params| params.to_string()); - ast_from_text(&format!("impl{2} {} for {}{2} {{}}", trait_, ty, ty_params)) + ast_from_text(&format!("impl{ty_params} {trait_} for {ty}{ty_params} {{}}")) } pub(crate) fn generic_arg_list() -> ast::GenericArgList { @@ -188,13 +190,13 @@ pub(crate) fn generic_arg_list() -> ast::GenericArgList { } pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { - ast_from_text(&format!("type __ = {};", name_ref)) + ast_from_text(&format!("type __ = {name_ref};")) } pub fn path_segment_ty(type_ref: ast::Type, trait_ref: Option<ast::PathType>) -> ast::PathSegment { let text = match trait_ref { - Some(trait_ref) => format!("fn f(x: <{} as {}>) {{}}", type_ref, trait_ref), - None => format!("fn f(x: <{}>) {{}}", type_ref), + Some(trait_ref) => format!("fn f(x: <{type_ref} as {trait_ref}>) {{}}"), + None => format!("fn f(x: <{type_ref}>) {{}}"), }; ast_from_text(&text) } @@ -212,15 +214,15 @@ pub fn path_segment_crate() -> ast::PathSegment { } pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { - ast_from_text(&format!("type __ = {};", segment)) + ast_from_text(&format!("type __ = {segment};")) } pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { - ast_from_text(&format!("{}::{}", qual, segment)) + ast_from_text(&format!("{qual}::{segment}")) } // FIXME: path concatenation operation doesn't make sense as AST op. pub fn path_concat(first: ast::Path, second: ast::Path) -> ast::Path { - ast_from_text(&format!("type __ = {}::{};", first, second)) + ast_from_text(&format!("type __ = {first}::{second};")) } pub fn path_from_segments( @@ -229,20 +231,20 @@ pub fn path_from_segments( ) -> ast::Path { let segments = segments.into_iter().map(|it| it.syntax().clone()).join("::"); ast_from_text(&if is_abs { - format!("fn f(x: ::{}) {{}}", segments) + format!("fn f(x: ::{segments}) {{}}") } else { - format!("fn f(x: {}) {{}}", segments) + format!("fn f(x: {segments}) {{}}") }) } pub fn join_paths(paths: impl IntoIterator<Item = ast::Path>) -> ast::Path { let paths = paths.into_iter().map(|it| it.syntax().clone()).join("::"); - ast_from_text(&format!("type __ = {};", paths)) + ast_from_text(&format!("type __ = {paths};")) } // FIXME: should not be pub pub fn path_from_text(text: &str) -> ast::Path { - ast_from_text(&format!("fn main() {{ let test = {}; }}", text)) + ast_from_text(&format!("fn main() {{ let test = {text}; }}")) } pub fn use_tree_glob() -> ast::UseTree { @@ -257,50 +259,50 @@ pub fn use_tree( let mut buf = "use ".to_string(); buf += &path.syntax().to_string(); if let Some(use_tree_list) = use_tree_list { - format_to!(buf, "::{}", use_tree_list); + format_to!(buf, "::{use_tree_list}"); } if add_star { buf += "::*"; } if let Some(alias) = alias { - format_to!(buf, " {}", alias); + format_to!(buf, " {alias}"); } ast_from_text(&buf) } pub fn use_tree_list(use_trees: impl IntoIterator<Item = ast::UseTree>) -> ast::UseTreeList { let use_trees = use_trees.into_iter().map(|it| it.syntax().clone()).join(", "); - ast_from_text(&format!("use {{{}}};", use_trees)) + ast_from_text(&format!("use {{{use_trees}}};")) } pub fn use_(visibility: Option<ast::Visibility>, use_tree: ast::UseTree) -> ast::Use { let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; - ast_from_text(&format!("{}use {};", visibility, use_tree)) + ast_from_text(&format!("{visibility}use {use_tree};")) } pub fn record_expr(path: ast::Path, fields: ast::RecordExprFieldList) -> ast::RecordExpr { - ast_from_text(&format!("fn f() {{ {} {} }}", path, fields)) + ast_from_text(&format!("fn f() {{ {path} {fields} }}")) } pub fn record_expr_field_list( fields: impl IntoIterator<Item = ast::RecordExprField>, ) -> ast::RecordExprFieldList { let fields = fields.into_iter().join(", "); - ast_from_text(&format!("fn f() {{ S {{ {} }} }}", fields)) + ast_from_text(&format!("fn f() {{ S {{ {fields} }} }}")) } pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { return match expr { - Some(expr) => from_text(&format!("{}: {}", name, expr)), + Some(expr) => from_text(&format!("{name}: {expr}")), None => from_text(&name.to_string()), }; fn from_text(text: &str) -> ast::RecordExprField { - ast_from_text(&format!("fn f() {{ S {{ {}, }} }}", text)) + ast_from_text(&format!("fn f() {{ S {{ {text}, }} }}")) } } @@ -311,9 +313,9 @@ pub fn record_field( ) -> ast::RecordField { let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; - ast_from_text(&format!("struct S {{ {}{}: {}, }}", visibility, name, ty)) + ast_from_text(&format!("struct S {{ {visibility}{name}: {ty}, }}")) } // TODO @@ -323,13 +325,13 @@ pub fn block_expr( ) -> ast::BlockExpr { let mut buf = "{\n".to_string(); for stmt in stmts.into_iter() { - format_to!(buf, " {}\n", stmt); + format_to!(buf, " {stmt}\n"); } if let Some(tail_expr) = tail_expr { - format_to!(buf, " {}\n", tail_expr); + format_to!(buf, " {tail_expr}\n"); } buf += "}"; - ast_from_text(&format!("fn f() {}", buf)) + ast_from_text(&format!("fn f() {buf}")) } /// Ideally this function wouldn't exist since it involves manual indenting. @@ -343,18 +345,18 @@ pub fn hacky_block_expr_with_comments( let mut buf = "{\n".to_string(); for node_or_token in elements.into_iter() { match node_or_token { - rowan::NodeOrToken::Node(n) => format_to!(buf, " {}\n", n), + rowan::NodeOrToken::Node(n) => format_to!(buf, " {n}\n"), rowan::NodeOrToken::Token(t) if t.kind() == SyntaxKind::COMMENT => { - format_to!(buf, " {}\n", t) + format_to!(buf, " {t}\n") } _ => (), } } if let Some(tail_expr) = tail_expr { - format_to!(buf, " {}\n", tail_expr); + format_to!(buf, " {tail_expr}\n"); } buf += "}"; - ast_from_text(&format!("fn f() {}", buf)) + ast_from_text(&format!("fn f() {buf}")) } pub fn expr_unit() -> ast::Expr { @@ -362,7 +364,7 @@ pub fn expr_unit() -> ast::Expr { } pub fn expr_literal(text: &str) -> ast::Literal { assert_eq!(text.trim(), text); - ast_from_text(&format!("fn f() {{ let _ = {}; }}", text)) + ast_from_text(&format!("fn f() {{ let _ = {text}; }}")) } pub fn expr_empty_block() -> ast::Expr { @@ -373,41 +375,41 @@ pub fn expr_path(path: ast::Path) -> ast::Expr { } pub fn expr_continue(label: Option<ast::Lifetime>) -> ast::Expr { match label { - Some(label) => expr_from_text(&format!("continue {}", label)), + Some(label) => expr_from_text(&format!("continue {label}")), None => expr_from_text("continue"), } } // Consider `op: SyntaxKind` instead for nicer syntax at the call-site? pub fn expr_bin_op(lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::Expr { - expr_from_text(&format!("{} {} {}", lhs, op, rhs)) + expr_from_text(&format!("{lhs} {op} {rhs}")) } pub fn expr_break(label: Option<ast::Lifetime>, expr: Option<ast::Expr>) -> ast::Expr { let mut s = String::from("break"); if let Some(label) = label { - format_to!(s, " {}", label); + format_to!(s, " {label}"); } if let Some(expr) = expr { - format_to!(s, " {}", expr); + format_to!(s, " {expr}"); } expr_from_text(&s) } pub fn expr_return(expr: Option<ast::Expr>) -> ast::Expr { match expr { - Some(expr) => expr_from_text(&format!("return {}", expr)), + Some(expr) => expr_from_text(&format!("return {expr}")), None => expr_from_text("return"), } } pub fn expr_try(expr: ast::Expr) -> ast::Expr { - expr_from_text(&format!("{}?", expr)) + expr_from_text(&format!("{expr}?")) } pub fn expr_await(expr: ast::Expr) -> ast::Expr { - expr_from_text(&format!("{}.await", expr)) + expr_from_text(&format!("{expr}.await")) } pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { - expr_from_text(&format!("match {} {}", expr, match_arm_list)) + expr_from_text(&format!("match {expr} {match_arm_list}")) } pub fn expr_if( condition: ast::Expr, @@ -415,66 +417,67 @@ pub fn expr_if( else_branch: Option<ast::ElseBranch>, ) -> ast::Expr { let else_branch = match else_branch { - Some(ast::ElseBranch::Block(block)) => format!("else {}", block), - Some(ast::ElseBranch::IfExpr(if_expr)) => format!("else {}", if_expr), + Some(ast::ElseBranch::Block(block)) => format!("else {block}"), + Some(ast::ElseBranch::IfExpr(if_expr)) => format!("else {if_expr}"), None => String::new(), }; - expr_from_text(&format!("if {} {} {}", condition, then_branch, else_branch)) + expr_from_text(&format!("if {condition} {then_branch} {else_branch}")) } pub fn expr_for_loop(pat: ast::Pat, expr: ast::Expr, block: ast::BlockExpr) -> ast::Expr { - expr_from_text(&format!("for {} in {} {}", pat, expr, block)) + expr_from_text(&format!("for {pat} in {expr} {block}")) } pub fn expr_loop(block: ast::BlockExpr) -> ast::Expr { - expr_from_text(&format!("loop {}", block)) + expr_from_text(&format!("loop {block}")) } pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { let token = token(op); - expr_from_text(&format!("{}{}", token, expr)) + expr_from_text(&format!("{token}{expr}")) } pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { - expr_from_text(&format!("{}{}", f, arg_list)) + expr_from_text(&format!("{f}{arg_list}")) } pub fn expr_method_call( receiver: ast::Expr, method: ast::NameRef, arg_list: ast::ArgList, ) -> ast::Expr { - expr_from_text(&format!("{}.{}{}", receiver, method, arg_list)) + expr_from_text(&format!("{receiver}.{method}{arg_list}")) } pub fn expr_macro_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { - expr_from_text(&format!("{}!{}", f, arg_list)) + expr_from_text(&format!("{f}!{arg_list}")) } pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr { - expr_from_text(&if exclusive { format!("&mut {}", expr) } else { format!("&{}", expr) }) + expr_from_text(&if exclusive { format!("&mut {expr}") } else { format!("&{expr}") }) } pub fn expr_closure(pats: impl IntoIterator<Item = ast::Param>, expr: ast::Expr) -> ast::Expr { let params = pats.into_iter().join(", "); - expr_from_text(&format!("|{}| {}", params, expr)) + expr_from_text(&format!("|{params}| {expr}")) } pub fn expr_field(receiver: ast::Expr, field: &str) -> ast::Expr { - expr_from_text(&format!("{}.{}", receiver, field)) + expr_from_text(&format!("{receiver}.{field}")) } pub fn expr_paren(expr: ast::Expr) -> ast::Expr { - expr_from_text(&format!("({})", expr)) + expr_from_text(&format!("({expr})")) } pub fn expr_tuple(elements: impl IntoIterator<Item = ast::Expr>) -> ast::Expr { let expr = elements.into_iter().format(", "); - expr_from_text(&format!("({})", expr)) + expr_from_text(&format!("({expr})")) } pub fn expr_assignment(lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { - expr_from_text(&format!("{} = {}", lhs, rhs)) + expr_from_text(&format!("{lhs} = {rhs}")) } fn expr_from_text(text: &str) -> ast::Expr { - ast_from_text(&format!("const C: () = {};", text)) + ast_from_text(&format!("const C: () = {text};")) } pub fn expr_let(pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr { - ast_from_text(&format!("const _: () = while let {} = {} {{}};", pattern, expr)) + ast_from_text(&format!("const _: () = while let {pattern} = {expr} {{}};")) } pub fn arg_list(args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList { - ast_from_text(&format!("fn main() {{ ()({}) }}", args.into_iter().format(", "))) + let args = args.into_iter().format(", "); + ast_from_text(&format!("fn main() {{ ()({args}) }}")) } pub fn ident_pat(ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat { @@ -485,7 +488,7 @@ pub fn ident_pat(ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat { if mut_ { s.push_str("mut "); } - format_to!(s, "{}", name); + format_to!(s, "{name}"); s.push_str(": ())"); ast_from_text(&s) } @@ -494,7 +497,7 @@ pub fn wildcard_pat() -> ast::WildcardPat { return from_text("_"); fn from_text(text: &str) -> ast::WildcardPat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } @@ -502,7 +505,7 @@ pub fn literal_pat(lit: &str) -> ast::LiteralPat { return from_text(lit); fn from_text(text: &str) -> ast::LiteralPat { - ast_from_text(&format!("fn f() {{ match x {{ {} => {{}} }} }}", text)) + ast_from_text(&format!("fn f() {{ match x {{ {text} => {{}} }} }}")) } } @@ -515,10 +518,10 @@ pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat { if count == 1 { pats_str.push(','); } - return from_text(&format!("({})", pats_str)); + return from_text(&format!("({pats_str})")); fn from_text(text: &str) -> ast::TuplePat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } @@ -527,46 +530,46 @@ pub fn tuple_struct_pat( pats: impl IntoIterator<Item = ast::Pat>, ) -> ast::TupleStructPat { let pats_str = pats.into_iter().join(", "); - return from_text(&format!("{}({})", path, pats_str)); + return from_text(&format!("{path}({pats_str})")); fn from_text(text: &str) -> ast::TupleStructPat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> ast::RecordPat { let pats_str = pats.into_iter().join(", "); - return from_text(&format!("{} {{ {} }}", path, pats_str)); + return from_text(&format!("{path} {{ {pats_str} }}")); fn from_text(text: &str) -> ast::RecordPat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } pub fn record_pat_with_fields(path: ast::Path, fields: ast::RecordPatFieldList) -> ast::RecordPat { - ast_from_text(&format!("fn f({} {}: ()))", path, fields)) + ast_from_text(&format!("fn f({path} {fields}: ()))")) } pub fn record_pat_field_list( fields: impl IntoIterator<Item = ast::RecordPatField>, ) -> ast::RecordPatFieldList { let fields = fields.into_iter().join(", "); - ast_from_text(&format!("fn f(S {{ {} }}: ()))", fields)) + ast_from_text(&format!("fn f(S {{ {fields} }}: ()))")) } pub fn record_pat_field(name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPatField { - ast_from_text(&format!("fn f(S {{ {}: {} }}: ()))", name_ref, pat)) + ast_from_text(&format!("fn f(S {{ {name_ref}: {pat} }}: ()))")) } pub fn record_pat_field_shorthand(name_ref: ast::NameRef) -> ast::RecordPatField { - ast_from_text(&format!("fn f(S {{ {} }}: ()))", name_ref)) + ast_from_text(&format!("fn f(S {{ {name_ref} }}: ()))")) } /// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. pub fn path_pat(path: ast::Path) -> ast::Pat { return from_text(&path.to_string()); fn from_text(text: &str) -> ast::Pat { - ast_from_text(&format!("fn f({}: ())", text)) + ast_from_text(&format!("fn f({text}: ())")) } } @@ -577,12 +580,12 @@ pub fn match_arm( ) -> ast::MatchArm { let pats_str = pats.into_iter().join(" | "); return match guard { - Some(guard) => from_text(&format!("{} if {} => {}", pats_str, guard, expr)), - None => from_text(&format!("{} => {}", pats_str, expr)), + Some(guard) => from_text(&format!("{pats_str} if {guard} => {expr}")), + None => from_text(&format!("{pats_str} => {expr}")), }; fn from_text(text: &str) -> ast::MatchArm { - ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) + ast_from_text(&format!("fn f() {{ match () {{{text}}} }}")) } } @@ -592,10 +595,10 @@ pub fn match_arm_with_guard( expr: ast::Expr, ) -> ast::MatchArm { let pats_str = pats.into_iter().join(" | "); - return from_text(&format!("{} if {} => {}", pats_str, guard, expr)); + return from_text(&format!("{pats_str} if {guard} => {expr}")); fn from_text(text: &str) -> ast::MatchArm { - ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text)) + ast_from_text(&format!("fn f() {{ match () {{{text}}} }}")) } } @@ -605,13 +608,14 @@ pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::Mat .map(|arm| { let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); let comma = if needs_comma { "," } else { "" }; - format!(" {}{}\n", arm.syntax(), comma) + let arm = arm.syntax(); + format!(" {arm}{comma}\n") }) .collect::<String>(); return from_text(&arms_str); fn from_text(text: &str) -> ast::MatchArmList { - ast_from_text(&format!("fn f() {{ match () {{\n{}}} }}", text)) + ast_from_text(&format!("fn f() {{ match () {{\n{text}}} }}")) } } @@ -620,10 +624,10 @@ pub fn where_pred( bounds: impl IntoIterator<Item = ast::TypeBound>, ) -> ast::WherePred { let bounds = bounds.into_iter().join(" + "); - return from_text(&format!("{}: {}", path, bounds)); + return from_text(&format!("{path}: {bounds}")); fn from_text(text: &str) -> ast::WherePred { - ast_from_text(&format!("fn f() where {} {{ }}", text)) + ast_from_text(&format!("fn f() where {text} {{ }}")) } } @@ -632,7 +636,7 @@ pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::Whe return from_text(preds.as_str()); fn from_text(text: &str) -> ast::WhereClause { - ast_from_text(&format!("fn f() where {} {{ }}", text)) + ast_from_text(&format!("fn f() where {text} {{ }}")) } } @@ -642,19 +646,19 @@ pub fn let_stmt( initializer: Option<ast::Expr>, ) -> ast::LetStmt { let mut text = String::new(); - format_to!(text, "let {}", pattern); + format_to!(text, "let {pattern}"); if let Some(ty) = ty { - format_to!(text, ": {}", ty); + format_to!(text, ": {ty}"); } match initializer { - Some(it) => format_to!(text, " = {};", it), + Some(it) => format_to!(text, " = {it};"), None => format_to!(text, ";"), }; - ast_from_text(&format!("fn f() {{ {} }}", text)) + ast_from_text(&format!("fn f() {{ {text} }}")) } pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt { let semi = if expr.is_block_like() { "" } else { ";" }; - ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi)) + ast_from_text(&format!("fn f() {{ {expr}{semi} (); }}")) } pub fn item_const( @@ -665,13 +669,13 @@ pub fn item_const( ) -> ast::Const { let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; - ast_from_text(&format!("{} const {}: {} = {};", visibility, name, ty, expr)) + ast_from_text(&format!("{visibility} const {name}: {ty} = {expr};")) } pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param { - ast_from_text(&format!("fn f({}: {}) {{ }}", pat, ty)) + ast_from_text(&format!("fn f({pat}: {ty}) {{ }}")) } pub fn self_param() -> ast::SelfParam { @@ -679,7 +683,7 @@ pub fn self_param() -> ast::SelfParam { } pub fn ret_type(ty: ast::Type) -> ast::RetType { - ast_from_text(&format!("fn f() -> {} {{ }}", ty)) + ast_from_text(&format!("fn f() -> {ty} {{ }}")) } pub fn param_list( @@ -688,30 +692,30 @@ pub fn param_list( ) -> ast::ParamList { let args = pats.into_iter().join(", "); let list = match self_param { - Some(self_param) if args.is_empty() => format!("fn f({}) {{ }}", self_param), - Some(self_param) => format!("fn f({}, {}) {{ }}", self_param, args), - None => format!("fn f({}) {{ }}", args), + Some(self_param) if args.is_empty() => format!("fn f({self_param}) {{ }}"), + Some(self_param) => format!("fn f({self_param}, {args}) {{ }}"), + None => format!("fn f({args}) {{ }}"), }; ast_from_text(&list) } pub fn type_param(name: ast::Name, ty: Option<ast::TypeBoundList>) -> ast::TypeParam { let bound = match ty { - Some(it) => format!(": {}", it), + Some(it) => format!(": {it}"), None => String::new(), }; - ast_from_text(&format!("fn f<{}{}>() {{ }}", name, bound)) + ast_from_text(&format!("fn f<{name}{bound}>() {{ }}")) } pub fn lifetime_param(lifetime: ast::Lifetime) -> ast::LifetimeParam { - ast_from_text(&format!("fn f<{}>() {{ }}", lifetime)) + ast_from_text(&format!("fn f<{lifetime}>() {{ }}")) } pub fn generic_param_list( pats: impl IntoIterator<Item = ast::GenericParam>, ) -> ast::GenericParamList { let args = pats.into_iter().join(", "); - ast_from_text(&format!("fn f<{}>() {{ }}", args)) + ast_from_text(&format!("fn f<{args}>() {{ }}")) } pub fn visibility_pub_crate() -> ast::Visibility { @@ -724,33 +728,33 @@ pub fn visibility_pub() -> ast::Visibility { pub fn tuple_field_list(fields: impl IntoIterator<Item = ast::TupleField>) -> ast::TupleFieldList { let fields = fields.into_iter().join(", "); - ast_from_text(&format!("struct f({});", fields)) + ast_from_text(&format!("struct f({fields});")) } pub fn record_field_list( fields: impl IntoIterator<Item = ast::RecordField>, ) -> ast::RecordFieldList { let fields = fields.into_iter().join(", "); - ast_from_text(&format!("struct f {{ {} }}", fields)) + ast_from_text(&format!("struct f {{ {fields} }}")) } pub fn tuple_field(visibility: Option<ast::Visibility>, ty: ast::Type) -> ast::TupleField { let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; - ast_from_text(&format!("struct f({}{});", visibility, ty)) + ast_from_text(&format!("struct f({visibility}{ty});")) } pub fn variant(name: ast::Name, field_list: Option<ast::FieldList>) -> ast::Variant { let field_list = match field_list { None => String::new(), Some(it) => match it { - ast::FieldList::RecordFieldList(record) => format!(" {}", record), - ast::FieldList::TupleFieldList(tuple) => format!("{}", tuple), + ast::FieldList::RecordFieldList(record) => format!(" {record}"), + ast::FieldList::TupleFieldList(tuple) => format!("{tuple}"), }, }; - ast_from_text(&format!("enum f {{ {}{} }}", name, field_list)) + ast_from_text(&format!("enum f {{ {name}{field_list} }}")) } pub fn fn_( @@ -763,23 +767,22 @@ pub fn fn_( is_async: bool, ) -> ast::Fn { let type_params = match type_params { - Some(type_params) => format!("{}", type_params), + Some(type_params) => format!("{type_params}"), None => "".into(), }; let ret_type = match ret_type { - Some(ret_type) => format!("{} ", ret_type), + Some(ret_type) => format!("{ret_type} "), None => "".into(), }; let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; let async_literal = if is_async { "async " } else { "" }; ast_from_text(&format!( - "{}{}fn {}{}{} {}{}", - visibility, async_literal, fn_name, type_params, params, ret_type, body + "{visibility}{async_literal}fn {fn_name}{type_params}{params} {ret_type}{body}", )) } @@ -793,13 +796,10 @@ pub fn struct_( let type_params = generic_param_list.map_or_else(String::new, |it| it.to_string()); let visibility = match visibility { None => String::new(), - Some(it) => format!("{} ", it), + Some(it) => format!("{it} "), }; - ast_from_text(&format!( - "{}struct {}{}{}{}", - visibility, strukt_name, type_params, field_list, semicolon - )) + ast_from_text(&format!("{visibility}struct {strukt_name}{type_params}{field_list}{semicolon}",)) } #[track_caller] @@ -808,7 +808,8 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { let node = match parse.tree().syntax().descendants().find_map(N::cast) { Some(it) => it, None => { - panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text) + let node = std::any::type_name::<N>(); + panic!("Failed to make ast node `{node}` from text {text}") } }; let node = node.clone_subtree(); @@ -824,7 +825,7 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken { .descendants_with_tokens() .filter_map(|it| it.into_token()) .find(|it| it.kind() == kind) - .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) + .unwrap_or_else(|| panic!("unhandled token: {kind:?}")) } pub mod tokens { @@ -863,7 +864,7 @@ pub mod tokens { pub fn literal(text: &str) -> SyntaxToken { assert_eq!(text.trim(), text); - let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text)); + let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {text}; }}")); lit.syntax().first_child_or_token().unwrap().into_token().unwrap() } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index 28976d837b8..ba72e64425b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -322,7 +322,7 @@ impl ast::IntNumber { pub fn float_value(&self) -> Option<f64> { let (_, text, _) = self.split_into_parts(); - text.parse::<f64>().ok() + text.replace('_', "").parse::<f64>().ok() } } @@ -361,7 +361,7 @@ impl ast::FloatNumber { pub fn value(&self) -> Option<f64> { let (text, _) = self.split_into_parts(); - text.parse::<f64>().ok() + text.replace('_', "").parse::<f64>().ok() } } @@ -397,6 +397,15 @@ mod tests { assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into()); } + fn check_float_value(lit: &str, expected: impl Into<Option<f64>> + Copy) { + assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.value(), expected.into()); + assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.float_value(), expected.into()); + } + + fn check_int_value(lit: &str, expected: impl Into<Option<u128>>) { + assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.value(), expected.into()); + } + #[test] fn test_float_number_suffix() { check_float_suffix("123.0", None); @@ -437,6 +446,14 @@ mod tests { check_string_value(r"\nfoobar", "\nfoobar"); check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\"); } + + #[test] + fn test_value_underscores() { + check_float_value("3.141592653589793_f64", 3.141592653589793_f64); + check_float_value("1__0.__0__f32", 10.0); + check_int_value("0b__1_0_", 2); + check_int_value("1_1_1_1_1_1", 111111); + } } impl ast::Char { diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs index 6d276622510..70b54843dba 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs @@ -169,10 +169,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String { quote! { impl AstNode for #name { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #(#kinds)|* => true, - _ => false, - } + matches!(kind, #(#kinds)|*) } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { @@ -253,10 +250,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String { } impl AstNode for #name { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #(#kinds)|* => true, - _ => false, - } + matches!(kind, #(#kinds)|*) } fn cast(syntax: SyntaxNode) -> Option<Self> { Self::can_cast(syntax.kind()).then(|| #name { syntax }) @@ -410,24 +404,17 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> String { impl SyntaxKind { pub fn is_keyword(self) -> bool { - match self { - #(#all_keywords)|* => true, - _ => false, - } + matches!(self, #(#all_keywords)|*) } pub fn is_punct(self) -> bool { - match self { - #(#punctuation)|* => true, - _ => false, - } + + matches!(self, #(#punctuation)|*) + } pub fn is_literal(self) -> bool { - match self { - #(#literals)|* => true, - _ => false, - } + matches!(self, #(#literals)|*) } pub fn from_keyword(ident: &str) -> Option<SyntaxKind> { diff --git a/src/tools/rust-analyzer/lib/la-arena/src/lib.rs b/src/tools/rust-analyzer/lib/la-arena/src/lib.rs index 50e8d06b660..ccaaf399176 100644 --- a/src/tools/rust-analyzer/lib/la-arena/src/lib.rs +++ b/src/tools/rust-analyzer/lib/la-arena/src/lib.rs @@ -322,6 +322,43 @@ impl<T> Arena<T> { .map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value)) } + /// Returns an iterator over the arena’s values. + /// + /// ``` + /// let mut arena = la_arena::Arena::new(); + /// let idx1 = arena.alloc(20); + /// let idx2 = arena.alloc(40); + /// let idx3 = arena.alloc(60); + /// + /// let mut iterator = arena.values(); + /// assert_eq!(iterator.next(), Some(&20)); + /// assert_eq!(iterator.next(), Some(&40)); + /// assert_eq!(iterator.next(), Some(&60)); + /// ``` + pub fn values(&mut self) -> impl Iterator<Item = &T> + ExactSizeIterator + DoubleEndedIterator { + self.data.iter() + } + + /// Returns an iterator over the arena’s mutable values. + /// + /// ``` + /// let mut arena = la_arena::Arena::new(); + /// let idx1 = arena.alloc(20); + /// + /// assert_eq!(arena[idx1], 20); + /// + /// let mut iterator = arena.values_mut(); + /// *iterator.next().unwrap() = 10; + /// drop(iterator); + /// + /// assert_eq!(arena[idx1], 10); + /// ``` + pub fn values_mut( + &mut self, + ) -> impl Iterator<Item = &mut T> + ExactSizeIterator + DoubleEndedIterator { + self.data.iter_mut() + } + /// Reallocates the arena to make it take up as little space as possible. pub fn shrink_to_fit(&mut self) { self.data.shrink_to_fit(); diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index de292d3305d..b306a527a7c 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -199,8 +199,7 @@ pub fn check( if channel != "nightly" && since == Version::CurrentPlaceholder { tidy_error!( bad, - "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {} channel", - version::VERSION_PLACEHOLDER + "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", ); } } |
