diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 2197dd68eaf69..a59dc870aa33d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1812,7 +1812,7 @@ where f.debug_struct("Layout") .field("size", size) .field("align", align) - .field("abi", backend_repr) + .field("backend_repr", backend_repr) .field("fields", fields) .field("largest_niche", largest_niche) .field("uninhabited", uninhabited) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fb6b36e1a09da..11fc409cf4333 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2641,6 +2641,8 @@ pub enum SelfKind { Value(Mutability), /// `&'lt self`, `&'lt mut self` Region(Option, Mutability), + /// `&'lt pin const self`, `&'lt pin mut self` + Pinned(Option, Mutability), /// `self: TYPE`, `mut self: TYPE` Explicit(P, Mutability), } @@ -2650,6 +2652,8 @@ impl SelfKind { match self { SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(), SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()), + SelfKind::Pinned(None, mutbl) => format!("&pin {}", mutbl.ptr_str()), + SelfKind::Pinned(Some(lt), mutbl) => format!("&{lt} pin {}", mutbl.ptr_str()), SelfKind::Value(_) | SelfKind::Explicit(_, _) => { unreachable!("if we had an explicit self, we wouldn't be here") } @@ -2666,11 +2670,13 @@ impl Param { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Ref(lt, MutTy { ref ty, mutbl }) - | TyKind::PinnedRef(lt, MutTy { ref ty, mutbl }) + TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { + Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) + } + TyKind::PinnedRef(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) + Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl))) } _ => Some(respan( self.pat.span.to(self.ty.span), @@ -2712,6 +2718,15 @@ impl Param { tokens: None, }), ), + SelfKind::Pinned(lt, mutbl) => ( + mutbl, + P(Ty { + id: DUMMY_NODE_ID, + kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }), + span, + tokens: None, + }), + ), }; Param { attrs, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c0188dde56518..f583206802845 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -136,6 +136,7 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Arc<[Symbol]>, allow_gen_future: Arc<[Symbol]>, + allow_pattern_type: Arc<[Symbol]>, allow_async_iterator: Arc<[Symbol]>, allow_for_await: Arc<[Symbol]>, allow_async_fn_traits: Arc<[Symbol]>, @@ -176,6 +177,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), + allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(), allow_gen_future: if tcx.features().async_fn_track_caller() { [sym::gen_future, sym::closure_track_caller].into() } else { @@ -926,7 +928,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(first_char) = constraint.ident.as_str().chars().next() && first_char.is_ascii_lowercase() { - tracing::info!(?data, ?data.inputs); let err = match (&data.inputs[..], &data.output) { ([_, ..], FnRetTy::Default(_)) => { errors::BadReturnTypeNotation::Inputs { span: data.inputs_span } @@ -1365,7 +1366,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } TyKind::Pat(ty, pat) => { - hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat)) + hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat, ty.span)) } TyKind::MacCall(_) => { span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 2dcfe7c745da5..728981dea5f83 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir as hir; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{self as hir, LangItem}; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; -use rustc_span::{Ident, Span}; +use rustc_span::{DesugaringKind, Ident, Span, kw}; use super::errors::{ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, @@ -430,22 +430,124 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind }) } - pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'hir hir::TyPat<'hir> { - self.arena.alloc(self.lower_ty_pat_mut(pattern)) + pub(crate) fn lower_ty_pat( + &mut self, + pattern: &TyPat, + base_type: Span, + ) -> &'hir hir::TyPat<'hir> { + self.arena.alloc(self.lower_ty_pat_mut(pattern, base_type)) } - fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> hir::TyPat<'hir> { + fn lower_ty_pat_mut(&mut self, pattern: &TyPat, base_type: Span) -> hir::TyPat<'hir> { // loop here to avoid recursion let pat_hir_id = self.lower_node_id(pattern.id); let node = match &pattern.kind { - TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range( - e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)), - e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)), - self.lower_range_end(end, e2.is_some()), + TyPatKind::Range(e1, e2, Spanned { node: end, span }) => hir::TyPatKind::Range( + e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)).unwrap_or_else(|| { + self.lower_ty_pat_range_end( + hir::LangItem::RangeMin, + span.shrink_to_lo(), + base_type, + ) + }), + e2.as_deref() + .map(|e| match end { + RangeEnd::Included(..) => self.lower_anon_const_to_const_arg(e), + RangeEnd::Excluded => self.lower_excluded_range_end(e), + }) + .unwrap_or_else(|| { + self.lower_ty_pat_range_end( + hir::LangItem::RangeMax, + span.shrink_to_hi(), + base_type, + ) + }), ), TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar), }; hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) } } + + /// Lowers the range end of an exclusive range (`2..5`) to an inclusive range 2..=(5 - 1). + /// This way the type system doesn't have to handle the distinction between inclusive/exclusive ranges. + fn lower_excluded_range_end(&mut self, e: &AnonConst) -> &'hir hir::ConstArg<'hir> { + let span = self.lower_span(e.value.span); + let unstable_span = self.mark_span_with_reason( + DesugaringKind::PatTyRange, + span, + Some(Arc::clone(&self.allow_pattern_type)), + ); + let anon_const = self.with_new_scopes(span, |this| { + let def_id = this.local_def_id(e.id); + let hir_id = this.lower_node_id(e.id); + let body = this.lower_body(|this| { + // Need to use a custom function as we can't just subtract `1` from a `char`. + let kind = hir::ExprKind::Path(this.make_lang_item_qpath( + hir::LangItem::RangeSub, + unstable_span, + None, + )); + let fn_def = this.arena.alloc(hir::Expr { hir_id: this.next_id(), kind, span }); + let args = this.arena.alloc([this.lower_expr_mut(&e.value)]); + ( + &[], + hir::Expr { + hir_id: this.next_id(), + kind: hir::ExprKind::Call(fn_def, args), + span, + }, + ) + }); + hir::AnonConst { def_id, hir_id, body, span } + }); + self.arena.alloc(hir::ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(self.arena.alloc(anon_const)), + }) + } + + /// When a range has no end specified (`1..` or `1..=`) or no start specified (`..5` or `..=5`), + /// we instead use a constant of the MAX/MIN of the type. + /// This way the type system does not have to handle the lack of a start/end. + fn lower_ty_pat_range_end( + &mut self, + lang_item: LangItem, + span: Span, + base_type: Span, + ) -> &'hir hir::ConstArg<'hir> { + let parent_def_id = self.current_hir_id_owner.def_id; + let node_id = self.next_node_id(); + + // Add a definition for the in-band const def. + // We're generating a range end that didn't exist in the AST, + // so the def collector didn't create the def ahead of time. That's why we have to do + // it here. + let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span); + let hir_id = self.lower_node_id(node_id); + + let unstable_span = self.mark_span_with_reason( + DesugaringKind::PatTyRange, + self.lower_span(span), + Some(Arc::clone(&self.allow_pattern_type)), + ); + let span = self.lower_span(base_type); + + let path_expr = hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Path(self.make_lang_item_qpath(lang_item, unstable_span, None)), + span, + }; + + let ct = self.with_new_scopes(span, |this| { + self.arena.alloc(hir::AnonConst { + def_id, + hir_id, + body: this.lower_body(|_this| (&[], path_expr)), + span, + }) + }); + let hir_id = self.next_id(); + self.arena.alloc(hir::ConstArg { kind: hir::ConstArgKind::Anon(ct), hir_id }) + } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 6b6244b05aa9b..d00c797755f3f 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -268,7 +268,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericArgs::Parenthesized(data) => match generic_args_mode { GenericArgsMode::ReturnTypeNotation => { - tracing::info!(?data, ?data.inputs); let err = match (&data.inputs[..], &data.output) { ([_, ..], FnRetTy::Default(_)) => { BadReturnTypeNotation::Inputs { span: data.inputs_span } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d747237f76dbc..01fc272a45897 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1783,6 +1783,13 @@ impl<'a> State<'a> { self.print_mutability(*m, false); self.word("self") } + SelfKind::Pinned(lt, m) => { + self.word("&"); + self.print_opt_lifetime(lt); + self.word("pin "); + self.print_mutability(*m, true); + self.word("self") + } SelfKind::Explicit(typ, m) => { self.print_mutability(*m, false); self.word("self"); diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 96fc9d7d9ac47..f0cce26f4e248 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -473,6 +473,15 @@ impl<'a> MetaItemListParserContext<'a> { { self.inside_delimiters.next(); return Some(MetaItemOrLitParser::Lit(lit)); + } else if let Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) = + self.inside_delimiters.peek() + { + self.inside_delimiters.next(); + return MetaItemListParserContext { + inside_delimiters: inner_tokens.iter().peekable(), + dcx: self.dcx, + } + .next(); } // or a path. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6d05696e146f1..480d90932b99a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2120,8 +2120,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // // Note that other checks (such as denying `dyn Send` -> `dyn // Debug`) are in `rustc_hir_typeck`. - if let ty::Dynamic(src_tty, _src_lt, _) = *src_tail.kind() - && let ty::Dynamic(dst_tty, dst_lt, _) = *dst_tail.kind() + if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind() + && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind() && src_tty.principal().is_some() && dst_tty.principal().is_some() { diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index d8db7d63f2dda..c2027863b00b1 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4f4b6785844dc..ce0b5a350e030 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -955,18 +955,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Handle the effect an FFI call might have on the state of allocations. /// This overapproximates the modifications which external code might make to memory: - /// We set all reachable allocations as initialized, mark all provenances as exposed + /// We set all reachable allocations as initialized, mark all reachable provenances as exposed /// and overwrite them with `Provenance::WILDCARD`. - pub fn prepare_for_native_call( - &mut self, - id: AllocId, - initial_prov: M::Provenance, - ) -> InterpResult<'tcx> { - // Expose provenance of the root allocation. - M::expose_provenance(self, initial_prov)?; - + /// + /// The allocations in `ids` are assumed to be already exposed. + pub fn prepare_for_native_call(&mut self, ids: Vec) -> InterpResult<'tcx> { let mut done = FxHashSet::default(); - let mut todo = vec![id]; + let mut todo = ids; while let Some(id) = todo.pop() { if !done.insert(id) { // We already saw this allocation before, don't process it again. diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 6ae97222f77fd..4cacc269709a9 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,3 +1,5 @@ +use std::alloc::Allocator; + #[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")] // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()` @@ -28,8 +30,8 @@ impls_dyn_send_neg!( [*const T where T: ?Sized] [*mut T where T: ?Sized] [std::ptr::NonNull where T: ?Sized] - [std::rc::Rc where T: ?Sized] - [std::rc::Weak where T: ?Sized] + [std::rc::Rc where T: ?Sized, A: Allocator] + [std::rc::Weak where T: ?Sized, A: Allocator] [std::sync::MutexGuard<'_, T> where T: ?Sized] [std::sync::RwLockReadGuard<'_, T> where T: ?Sized] [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized] @@ -96,8 +98,8 @@ impls_dyn_sync_neg!( [std::cell::RefCell where T: ?Sized] [std::cell::UnsafeCell where T: ?Sized] [std::ptr::NonNull where T: ?Sized] - [std::rc::Rc where T: ?Sized] - [std::rc::Weak where T: ?Sized] + [std::rc::Rc where T: ?Sized, A: Allocator] + [std::rc::Weak where T: ?Sized, A: Allocator] [std::cell::OnceCell where T] [std::sync::mpsc::Receiver where T] [std::sync::mpsc::Sender where T] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f2b133f56773b..f69e756a3e1b5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -626,7 +626,6 @@ pub enum StashKey { MaybeFruTypo, CallAssocMethod, AssociatedTypeSuggestion, - MaybeForgetReturn, /// Query cycle detected, stashing in favor of a better error. Cycle, UndeterminedMacroResolution, diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index d4604c27e6da3..b04fd1b48f7ad 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -78,8 +78,8 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream { /// See [rustc_fluent_macro::fluent_messages]. pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let crate_name = std::env::var("CARGO_PKG_NAME") - // If `CARGO_PKG_NAME` is missing, then we're probably running in a test, so use + let crate_name = std::env::var("CARGO_CRATE_NAME") + // If `CARGO_CRATE_NAME` is missing, then we're probably running in a test, so use // `no_crate`. .unwrap_or_else(|_| "no_crate".to_string()) .replace("rustc_", ""); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 399f1f4b23730..df305e6e769d9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1600,7 +1600,7 @@ pub struct PatField<'hir> { pub span: Span, } -#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic, Hash, Eq, Encodable, Decodable)] pub enum RangeEnd { Included, Excluded, @@ -1668,7 +1668,7 @@ pub enum PatExprKind<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TyPatKind<'hir> { /// A range pattern (e.g., `1..=2` or `1..2`). - Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd), + Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>), /// A placeholder for a pattern that wasn't well formed in some way. Err(ErrorGuaranteed), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index e349e23f7dcf5..41eb5b45bd1e0 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -708,9 +708,9 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result { try_visit!(visitor.visit_id(pattern.hir_id)); match pattern.kind { - TyPatKind::Range(lower_bound, upper_bound, _) => { - visit_opt!(visitor, visit_const_arg_unambig, lower_bound); - visit_opt!(visitor, visit_const_arg_unambig, upper_bound); + TyPatKind::Range(lower_bound, upper_bound) => { + try_visit!(visitor.visit_const_arg_unambig(lower_bound)); + try_visit!(visitor.visit_const_arg_unambig(upper_bound)); } TyPatKind::Err(_) => (), } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index f5626937ec456..c3b14a4e06c79 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -418,6 +418,9 @@ language_item_table! { Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None; RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None; RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None; + RangeMax, sym::RangeMax, range_max, Target::AssocConst, GenericRequirement::Exact(0); + RangeMin, sym::RangeMin, range_min, Target::AssocConst, GenericRequirement::Exact(0); + RangeSub, sym::RangeSub, range_sub, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); // `new_range` types that are `Copy + IntoIterator` RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 3f75cce009225..935f4de6c58c8 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -244,9 +244,6 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a .help = consider moving this inherent impl into the crate defining the type if possible .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items -hir_analysis_invalid_base_type = `{$ty}` is not a valid base type for range patterns - .note = range patterns only support integers - hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}` .note = type of `self` must not be a method generic parameter type @@ -278,13 +275,6 @@ hir_analysis_invalid_union_field = hir_analysis_invalid_union_field_sugg = wrap the field type in `ManuallyDrop<...>` -hir_analysis_invalid_unsafe_field = - field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be unsafe - .note = unsafe fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` - -hir_analysis_invalid_unsafe_field_sugg = - wrap the field type in `ManuallyDrop<...>` - hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl .label = const parameter declared here @@ -620,6 +610,8 @@ hir_analysis_variances_of = {$variances} hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause .label = `main` cannot have a `where` clause +hir_analysis_within_macro = due to this macro variable + hir_analysis_wrong_number_of_generic_arguments_to_intrinsic = intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected} .label = expected {$expected} {$descr} {$expected -> diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs similarity index 62% rename from compiler/rustc_hir_analysis/src/check/dropck.rs rename to compiler/rustc_hir_analysis/src/check/always_applicable.rs index d7dfe482da449..ba5b61d3fce0b 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -1,8 +1,15 @@ +//! This module contains methods that assist in checking that impls are general +//! enough, i.e. that they always apply to every valid instantaiton of the ADT +//! they're implemented for. +//! +//! This is necessary for `Drop` and negative impls to be well-formed. + use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; +use rustc_middle::span_bug; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode}; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -27,11 +34,12 @@ use crate::hir::def_id::{DefId, LocalDefId}; /// 3. Any bounds on the generic parameters must be reflected in the /// struct/enum definition for the nominal type itself (i.e. /// cannot do `struct S; impl Drop for S { ... }`). -/// pub(crate) fn check_drop_impl( tcx: TyCtxt<'_>, drop_impl_did: DefId, ) -> Result<(), ErrorGuaranteed> { + let drop_impl_did = drop_impl_did.expect_local(); + match tcx.impl_polarity(drop_impl_did) { ty::ImplPolarity::Positive => {} ty::ImplPolarity::Negative => { @@ -45,55 +53,107 @@ pub(crate) fn check_drop_impl( })); } } - let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity(); - match dtor_self_type.kind() { + + tcx.ensure_ok().orphan_check_impl(drop_impl_did)?; + + let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity(); + + match dtor_impl_trait_ref.self_ty().kind() { ty::Adt(adt_def, adt_to_impl_args) => { - ensure_drop_params_and_item_params_correspond( + ensure_impl_params_and_item_params_correspond( tcx, - drop_impl_did.expect_local(), + drop_impl_did, adt_def.did(), adt_to_impl_args, )?; - ensure_drop_predicates_are_implied_by_item_defn( + ensure_impl_predicates_are_implied_by_item_defn( tcx, - drop_impl_did.expect_local(), - adt_def.did().expect_local(), + drop_impl_did, + adt_def.did(), adt_to_impl_args, ) } _ => { - // Destructors only work on nominal types. This was - // already checked by coherence, but compilation may - // not have been terminated. - let span = tcx.def_span(drop_impl_did); - let reported = tcx.dcx().span_delayed_bug( - span, - format!("should have been rejected by coherence check: {dtor_self_type}"), - ); - Err(reported) + span_bug!(tcx.def_span(drop_impl_did), "incoherent impl of Drop"); } } } -fn ensure_drop_params_and_item_params_correspond<'tcx>( +pub(crate) fn check_negative_auto_trait_impl<'tcx>( tcx: TyCtxt<'tcx>, - drop_impl_did: LocalDefId, - self_type_did: DefId, + impl_def_id: LocalDefId, + impl_trait_ref: ty::TraitRef<'tcx>, + polarity: ty::ImplPolarity, +) -> Result<(), ErrorGuaranteed> { + let ty::ImplPolarity::Negative = polarity else { + return Ok(()); + }; + + if !tcx.trait_is_auto(impl_trait_ref.def_id) { + return Ok(()); + } + + if tcx.defaultness(impl_def_id).is_default() { + tcx.dcx().span_delayed_bug(tcx.def_span(impl_def_id), "default impl cannot be negative"); + } + + tcx.ensure_ok().orphan_check_impl(impl_def_id)?; + + match impl_trait_ref.self_ty().kind() { + ty::Adt(adt_def, adt_to_impl_args) => { + ensure_impl_params_and_item_params_correspond( + tcx, + impl_def_id, + adt_def.did(), + adt_to_impl_args, + )?; + + ensure_impl_predicates_are_implied_by_item_defn( + tcx, + impl_def_id, + adt_def.did(), + adt_to_impl_args, + ) + } + _ => { + if tcx.features().auto_traits() { + // NOTE: We ignore the applicability check for negative auto impls + // defined in libcore. In the (almost impossible) future where we + // stabilize auto impls, then the proper applicability check MUST + // be implemented here to handle non-ADT rigid types. + Ok(()) + } else { + span_bug!(tcx.def_span(impl_def_id), "incoherent impl of negative auto trait"); + } + } + } +} + +fn ensure_impl_params_and_item_params_correspond<'tcx>( + tcx: TyCtxt<'tcx>, + impl_def_id: LocalDefId, + adt_def_id: DefId, adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else { return Ok(()); }; - let drop_impl_span = tcx.def_span(drop_impl_did); - let item_span = tcx.def_span(self_type_did); - let self_descr = tcx.def_descr(self_type_did); + let impl_span = tcx.def_span(impl_def_id); + let item_span = tcx.def_span(adt_def_id); + let self_descr = tcx.def_descr(adt_def_id); + let polarity = match tcx.impl_polarity(impl_def_id) { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; + let trait_name = tcx + .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait")); let mut err = struct_span_code_err!( tcx.dcx(), - drop_impl_span, + impl_span, E0366, - "`Drop` impls cannot be specialized" + "`{polarity}{trait_name}` impls cannot be specialized", ); match arg { ty::util::NotUniqueParam::DuplicateParam(arg) => { @@ -116,17 +176,22 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( /// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be /// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are /// implied by the ADT being well formed. -fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( +fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, - drop_impl_def_id: LocalDefId, - adt_def_id: LocalDefId, + impl_def_id: LocalDefId, + adt_def_id: DefId, adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let impl_span = tcx.def_span(drop_impl_def_id.to_def_id()); - + let impl_span = tcx.def_span(impl_def_id.to_def_id()); + let trait_name = tcx + .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait")); + let polarity = match tcx.impl_polarity(impl_def_id) { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; // Take the param-env of the adt and instantiate the args that show up in // the implementation's self type. This gives us the assumptions that the // self ty of the implementation is allowed to know just from it being a @@ -145,17 +210,21 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let adt_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); - let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id()); + let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id()); let fresh_adt_ty = - tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty(); + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty(); ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty) - .unwrap(); + .expect("equating fully generic trait ref should never fail"); - for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) { - let normalize_cause = traits::ObligationCause::misc(span, adt_def_id); + for (clause, span) in tcx.predicates_of(impl_def_id).instantiate(tcx, fresh_impl_args) { + let normalize_cause = traits::ObligationCause::misc(span, impl_def_id); let pred = ocx.normalize(&normalize_cause, adt_env, clause); - let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl); + let cause = traits::ObligationCause::new( + span, + impl_def_id, + ObligationCauseCode::AlwaysApplicableImpl, + ); ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred)); } @@ -173,13 +242,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let root_predicate = error.root_obligation.predicate; if root_predicates.insert(root_predicate) { let item_span = tcx.def_span(adt_def_id); - let self_descr = tcx.def_descr(adt_def_id.to_def_id()); + let self_descr = tcx.def_descr(adt_def_id); guar = Some( struct_span_code_err!( tcx.dcx(), error.root_obligation.cause.span, E0367, - "`Drop` impl requires `{root_predicate}` \ + "`{polarity}{trait_name}` impl requires `{root_predicate}` \ but the {self_descr} it is implemented for does not", ) .with_span_note(item_span, "the implementor must specify the same requirement") @@ -190,12 +259,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( return Err(guar.unwrap()); } - let errors = ocx.infcx.resolve_regions(adt_def_id, adt_env, []); + let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []); if !errors.is_empty() { let mut guar = None; for error in errors { let item_span = tcx.def_span(adt_def_id); - let self_descr = tcx.def_descr(adt_def_id.to_def_id()); + let self_descr = tcx.def_descr(adt_def_id); let outlives = match error { RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"), RegionResolutionError::GenericBoundFailure(_, generic, r) => { @@ -212,7 +281,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx.dcx(), error.origin().span(), E0367, - "`Drop` impl requires `{outlives}` \ + "`{polarity}{trait_name}` impl requires `{outlives}` \ but the {self_descr} it is implemented for does not", ) .with_span_note(item_span, "the implementor must specify the same requirement") diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f89f41aaf8afd..8f9997cb62ca4 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -70,7 +70,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); - check_unsafe_fields(tcx, def_id); } fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { @@ -144,36 +143,6 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b true } -/// Check that the unsafe fields do not need dropping. -fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) { - let span = tcx.def_span(item_def_id); - let def = tcx.adt_def(item_def_id); - - let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); - let args = ty::GenericArgs::identity_for_item(tcx, item_def_id); - - for field in def.all_fields() { - if !field.safety.is_unsafe() { - continue; - } - - if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) { - let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else { - unreachable!("field has to correspond to hir field") - }; - let ty_span = field.ty.span; - tcx.dcx().emit_err(errors::InvalidUnsafeField { - field_span: field.span, - sugg: errors::InvalidUnsafeFieldSuggestion { - lo: ty_span.shrink_to_lo(), - hi: ty_span.shrink_to_hi(), - }, - note: (), - }); - } - } -} - /// Check that a `static` is inhabited. fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Make sure statics are inhabited. @@ -1512,7 +1481,6 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { detect_discriminant_duplicate(tcx, def); check_transparent(tcx, def); - check_unsafe_fields(tcx, def_id); } /// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 89a759f7ddaeb..9c28fac809da7 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -62,9 +62,9 @@ a type parameter). */ +pub mod always_applicable; mod check; mod compare_impl_item; -pub mod dropck; mod entry; pub mod intrinsic; pub mod intrinsicck; @@ -113,11 +113,11 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl) + tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl) + tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) } /// Given a `DefId` for an opaque type in return position, find its parent item's return diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 0245d4c9fe4b6..b5c6c2f386192 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -16,6 +16,7 @@ use rustc_span::{ErrorGuaranteed, sym}; use rustc_type_ir::elaborate; use tracing::debug; +use crate::check::always_applicable; use crate::errors; mod builtin; @@ -24,11 +25,12 @@ mod inherent_impls_overlap; mod orphan; mod unsafety; -fn check_impl( - tcx: TyCtxt<'_>, +fn check_impl<'tcx>( + tcx: TyCtxt<'tcx>, impl_def_id: LocalDefId, - trait_ref: ty::TraitRef<'_>, - trait_def: &ty::TraitDef, + trait_ref: ty::TraitRef<'tcx>, + trait_def: &'tcx ty::TraitDef, + polarity: ty::ImplPolarity, ) -> Result<(), ErrorGuaranteed> { debug!( "(checking implementation) adding impl for trait '{:?}', item '{}'", @@ -44,6 +46,12 @@ fn check_impl( enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def) .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def)) + .and(always_applicable::check_negative_auto_trait_impl( + tcx, + impl_def_id, + trait_ref, + polarity, + )) } fn enforce_trait_manually_implementable( @@ -154,16 +162,16 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure_ok().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); - let trait_ref = trait_header.trait_ref.instantiate_identity(); + let impl_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = impl_header.trait_ref.instantiate_identity(); let trait_def = tcx.trait_def(trait_ref.def_id); res = res - .and(check_impl(tcx, impl_def_id, trait_ref, trait_def)) + .and(check_impl(tcx, impl_def_id, trait_ref, trait_def, impl_header.polarity)) .and(check_object_overlap(tcx, impl_def_id, trait_ref)) - .and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)) + .and(unsafety::check_item(tcx, impl_def_id, impl_header, trait_def)) .and(tcx.ensure_ok().orphan_check_impl(impl_def_id)) - .and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header)); + .and(builtin::check_trait(tcx, def_id, impl_def_id, impl_header)); } res diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 852533ff5c954..4c6c2504126a8 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -11,8 +11,6 @@ use rustc_middle::ty::Ty; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -mod pattern_types; -pub(crate) use pattern_types::*; pub(crate) mod wrong_number_of_generic_args; mod precise_captures; @@ -84,6 +82,8 @@ pub(crate) struct AssocItemNotFound<'a> { pub label: Option>, #[subdiagnostic] pub sugg: Option>, + #[label(hir_analysis_within_macro)] + pub within_macro_span: Option, } #[derive(Subdiagnostic)] @@ -710,17 +710,6 @@ pub(crate) struct InvalidUnionField { pub note: (), } -#[derive(Diagnostic)] -#[diag(hir_analysis_invalid_unsafe_field, code = E0740)] -pub(crate) struct InvalidUnsafeField { - #[primary_span] - pub field_span: Span, - #[subdiagnostic] - pub sugg: InvalidUnsafeFieldSuggestion, - #[note] - pub note: (), -} - #[derive(Diagnostic)] #[diag(hir_analysis_return_type_notation_on_non_rpitit)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { @@ -742,18 +731,6 @@ pub(crate) struct InvalidUnionFieldSuggestion { pub hi: Span, } -#[derive(Subdiagnostic)] -#[multipart_suggestion( - hir_analysis_invalid_unsafe_field_sugg, - applicability = "machine-applicable" -)] -pub(crate) struct InvalidUnsafeFieldSuggestion { - #[suggestion_part(code = "std::mem::ManuallyDrop<")] - pub lo: Span, - #[suggestion_part(code = ">")] - pub hi: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_return_type_notation_equality_bound)] pub(crate) struct ReturnTypeNotationEqualityBound { diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs deleted file mode 100644 index ec7b3aaa1c14c..0000000000000 --- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs +++ /dev/null @@ -1,14 +0,0 @@ -use rustc_macros::Diagnostic; -use rustc_middle::ty::Ty; -use rustc_span::Span; - -#[derive(Diagnostic)] -#[diag(hir_analysis_invalid_base_type)] -pub(crate) struct InvalidBaseType<'tcx> { - pub ty: Ty<'tcx>, - #[primary_span] - pub ty_span: Span, - pub pat: &'static str, - #[note] - pub pat_span: Span, -} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d51fd7f7e78ab..ace5e34b38249 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -151,6 +151,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qself: &qself_str, label: None, sugg: None, + // Try to get the span of the identifier within the path's syntax context + // (if that's different). + within_macro_span: assoc_name.span.within_macro(span, tcx.sess.source_map()), }; if is_dummy { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index d044688246f9c..dd6c40bfbb8dc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -55,9 +55,7 @@ use tracing::{debug, instrument}; use self::errors::assoc_kind_str; use crate::check::check_abi_fn_ptr; -use crate::errors::{ - AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed, -}; +use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -2692,28 +2690,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let ty_span = ty.span; let ty = self.lower_ty(ty); let pat_ty = match pat.kind { - hir::TyPatKind::Range(start, end, include_end) => { - let ty = match ty.kind() { - ty::Int(_) | ty::Uint(_) | ty::Char => ty, - _ => Ty::new_error( - tcx, - self.dcx().emit_err(InvalidBaseType { - ty, - pat: "range", + hir::TyPatKind::Range(start, end) => { + let (ty, start, end) = match ty.kind() { + // Keep this list of types in sync with the list of types that + // the `RangePattern` trait is implemented for. + ty::Int(_) | ty::Uint(_) | ty::Char => { + let start = self.lower_const_arg(start, FeedConstTy::No); + let end = self.lower_const_arg(end, FeedConstTy::No); + (ty, start, end) + } + _ => { + let guar = self.dcx().span_delayed_bug( ty_span, - pat_span: pat.span, - }), - ), - }; - let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)); - let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)); - - let include_end = match include_end { - hir::RangeEnd::Included => true, - hir::RangeEnd::Excluded => false, + "invalid base type for range pattern", + ); + let errc = ty::Const::new_error(tcx, guar); + (Ty::new_error(tcx, guar), errc, errc) + } }; - let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end }); + let pat = tcx.mk_pat(ty::PatternKind::Range { start, end }); Ty::new_pat(tcx, ty, pat) } hir::TyPatKind::Err(e) => Ty::new_error(tcx, e), diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index e954d2b9ea48e..8475903c68fde 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -252,13 +252,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::Pat(typ, pat) => { match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { - if let Some(start) = start { - self.add_constraints_from_const(current, start, variance); - } - if let Some(end) = end { - self.add_constraints_from_const(current, end, variance); - } + ty::PatternKind::Range { start, end } => { + self.add_constraints_from_const(current, start, variance); + self.add_constraints_from_const(current, end, variance); } } self.add_constraints_from_ty(current, typ, variance); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1658c8dac6768..147b42c049089 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1943,17 +1943,10 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { - TyPatKind::Range(begin, end, end_kind) => { - if let Some(expr) = begin { - self.print_const_arg(expr); - } - match end_kind { - RangeEnd::Included => self.word("..."), - RangeEnd::Excluded => self.word(".."), - } - if let Some(expr) = end { - self.print_const_arg(expr); - } + TyPatKind::Range(begin, end) => { + self.print_const_arg(begin); + self.word("..="); + self.print_const_arg(end); } TyPatKind::Err(_) => { self.popen(); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index cbe677171a0b3..2a89a03e0aa49 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3069,7 +3069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}", ident, base, expr, base_ty ); - let mut err = self.no_such_field_err(ident, base_ty, base.hir_id); + let mut err = self.no_such_field_err(ident, base_ty, expr); match *base_ty.peel_refs().kind() { ty::Array(_, len) => { @@ -3282,18 +3282,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - fn no_such_field_err(&self, field: Ident, expr_t: Ty<'tcx>, id: HirId) -> Diag<'_> { + fn no_such_field_err( + &self, + field: Ident, + base_ty: Ty<'tcx>, + expr: &hir::Expr<'tcx>, + ) -> Diag<'_> { let span = field.span; - debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); + debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, base_ty); - let mut err = self.dcx().create_err(NoFieldOnType { span, ty: expr_t, field }); - if expr_t.references_error() { + let mut err = self.dcx().create_err(NoFieldOnType { span, ty: base_ty, field }); + if base_ty.references_error() { err.downgrade_to_delayed_bug(); } + if let Some(within_macro_span) = span.within_macro(expr.span, self.tcx.sess.source_map()) { + err.span_label(within_macro_span, "due to this macro variable"); + } + // try to add a suggestion in case the field is a nested field of a field of the Adt - let mod_id = self.tcx.parent_module(id).to_def_id(); - let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind() + let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); + let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind() && (self.tcx.is_diagnostic_item(sym::Result, def.did()) || self.tcx.is_diagnostic_item(sym::Option, def.did())) && let Some(arg) = args.get(0) @@ -3301,10 +3310,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { (ty, "unwrap().") } else { - (expr_t, "") + (base_ty, "") }; for (found_fields, args) in - self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, id) + self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, expr.hir_id) { let field_names = found_fields.iter().map(|field| field.name).collect::>(); let mut candidate_fields: Vec<_> = found_fields @@ -3317,7 +3326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args, vec![], mod_id, - id, + expr.hir_id, ) }) .map(|mut field_path| { @@ -3328,7 +3337,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidate_fields.sort(); let len = candidate_fields.len(); - if len > 0 { + // Don't suggest `.field` if the base expr is from a different + // syntax context than the field. + if len > 0 && expr.span.eq_ctxt(field.span) { err.span_suggestions( field.span.shrink_to_lo(), format!( @@ -3963,7 +3974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => (), }; - self.no_such_field_err(field, container, expr.hir_id).emit(); + self.no_such_field_err(field, container, expr).emit(); break; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 054e3bcb67c3d..c46a42c5de1e3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -669,12 +669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !errors.is_empty() { self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); - let errors_causecode = errors - .iter() - .map(|e| (e.obligation.cause.span, e.root_obligation.cause.code().clone())) - .collect::>(); self.err_ctxt().report_fulfillment_errors(errors); - self.collect_unused_stmts_for_coerce_return_ty(errors_causecode); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 82e99ca7afa2f..db947b6744da6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3,9 +3,7 @@ use std::{fmt, iter, mem}; use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; -use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, listify, pluralize, -}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -2193,62 +2191,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(super) fn collect_unused_stmts_for_coerce_return_ty( - &self, - errors_causecode: Vec<(Span, ObligationCauseCode<'tcx>)>, - ) { - for (span, code) in errors_causecode { - self.dcx().try_steal_modify_and_emit_err(span, StashKey::MaybeForgetReturn, |err| { - if let Some(fn_sig) = self.body_fn_sig() - && let ObligationCauseCode::WhereClauseInExpr(_, _, binding_hir_id, ..) = code - && !fn_sig.output().is_unit() - { - let mut block_num = 0; - let mut found_semi = false; - for (hir_id, node) in self.tcx.hir_parent_iter(binding_hir_id) { - // Don't proceed into parent bodies - if hir_id.owner != binding_hir_id.owner { - break; - } - match node { - hir::Node::Stmt(stmt) => { - if let hir::StmtKind::Semi(expr) = stmt.kind { - let expr_ty = self.typeck_results.borrow().expr_ty(expr); - let return_ty = fn_sig.output(); - if !matches!(expr.kind, hir::ExprKind::Ret(..)) - && self.may_coerce(expr_ty, return_ty) - { - found_semi = true; - } - } - } - hir::Node::Block(_block) => { - if found_semi { - block_num += 1; - } - } - hir::Node::Item(item) => { - if let hir::ItemKind::Fn { .. } = item.kind { - break; - } - } - _ => {} - } - } - if block_num > 1 && found_semi { - err.span_suggestion_verbose( - // use the span of the *whole* expr - self.tcx.hir().span(binding_hir_id).shrink_to_lo(), - "you might have meant to return this to infer its type parameters", - "return ", - Applicability::MaybeIncorrect, - ); - } - } - }); - } - } - /// Given a vector of fulfillment errors, try to adjust the spans of the /// errors to more accurately point at the cause of the failure. /// diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 18218a7a0a641..cb1e89fb9e593 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); } - let (span, sugg_span, source, item_name, args) = match self.tcx.hir_node(call_id) { + let (span, expr_span, source, item_name, args) = match self.tcx.hir_node(call_id) { hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::MethodCall(segment, rcvr, args, _), span, @@ -194,6 +194,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { node => unreachable!("{node:?}"), }; + // Try to get the span of the identifier within the expression's syntax context + // (if that's different). + let within_macro_span = span.within_macro(expr_span, self.tcx.sess.source_map()); + // Avoid suggestions when we don't know what's going on. if let Err(guar) = rcvr_ty.error_reported() { return guar; @@ -207,10 +211,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_id, source, args, - sugg_span, + expr_span, &mut no_match_data, expected, trait_missing_method, + within_macro_span, ), MethodError::Ambiguity(mut sources) => { @@ -221,6 +226,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "multiple applicable items in scope" ); err.span_label(item_name.span, format!("multiple `{item_name}` found")); + if let Some(within_macro_span) = within_macro_span { + err.span_label(within_macro_span, "due to this macro variable"); + } self.note_candidates_on_method_error( rcvr_ty, @@ -230,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, &mut err, &mut sources, - Some(sugg_span), + Some(expr_span), ); err.emit() } @@ -252,6 +260,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .span_if_local(def_id) .unwrap_or_else(|| self.tcx.def_span(def_id)); err.span_label(sp, format!("private {kind} defined here")); + if let Some(within_macro_span) = within_macro_span { + err.span_label(within_macro_span, "due to this macro variable"); + } self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true); err.emit() } @@ -268,6 +279,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !needs_mut { err.span_label(bound_span, "this has a `Sized` requirement"); } + if let Some(within_macro_span) = within_macro_span { + err.span_label(within_macro_span, "due to this macro variable"); + } if !candidates.is_empty() { let help = format!( "{an}other candidate{s} {were} found in the following trait{s}", @@ -581,6 +595,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, trait_missing_method: bool, + within_macro_span: Option, ) -> ErrorGuaranteed { let mode = no_match_data.mode; let tcx = self.tcx; @@ -721,6 +736,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if tcx.sess.source_map().is_multiline(sugg_span) { err.span_label(sugg_span.with_hi(span.lo()), ""); } + if let Some(within_macro_span) = within_macro_span { + err.span_label(within_macro_span, "due to this macro variable"); + } if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 { ty_str = short_ty_str; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index d2b08eab47916..fcadbfc3c4a7e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -882,27 +882,13 @@ fn ty_is_known_nonnull<'tcx>( || Option::unwrap_or_default( try { match **pat { - ty::PatternKind::Range { start, end, include_end } => { - match (start, end) { - (Some(start), None) => { - start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0 - } - (Some(start), Some(end)) => { - let start = - start.try_to_value()?.try_to_bits(tcx, typing_env)?; - let end = - end.try_to_value()?.try_to_bits(tcx, typing_env)?; - - if include_end { - // This also works for negative numbers, as we just need - // to ensure we aren't wrapping over zero. - start > 0 && end >= start - } else { - start > 0 && end > start - } - } - _ => false, - } + ty::PatternKind::Range { start, end } => { + let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?; + let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?; + + // This also works for negative numbers, as we just need + // to ensure we aren't wrapping over zero. + start > 0 && end >= start } } }, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 697a0e6592df0..ba65a7118155c 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -470,7 +470,7 @@ impl Allocation // Find the provenance. let (offset, _prov) = self .provenance - .range_get_ptrs(range, cx) + .range_ptrs_get(range, cx) .first() .copied() .expect("there must be provenance somewhere here"); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 82fb5f33b4c81..c9525df1f7940 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -67,7 +67,7 @@ impl ProvenanceMap { } impl ProvenanceMap { - fn adjusted_range(range: AllocRange, cx: &impl HasDataLayout) -> Range { + fn adjusted_range_ptrs(range: AllocRange, cx: &impl HasDataLayout) -> Range { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let adjusted_start = Size::from_bytes( @@ -79,26 +79,21 @@ impl ProvenanceMap { /// Returns all ptr-sized provenance in the given range. /// If the range has length 0, returns provenance that crosses the edge between `start-1` and /// `start`. - pub(super) fn range_get_ptrs( + pub(super) fn range_ptrs_get( &self, range: AllocRange, cx: &impl HasDataLayout, ) -> &[(Size, Prov)] { - self.ptrs.range(Self::adjusted_range(range, cx)) + self.ptrs.range(Self::adjusted_range_ptrs(range, cx)) } - /// `pm.range_get_ptrs_is_empty(r, cx)` == `pm.range_get_ptrs(r, cx).is_empty()`, but is - /// faster. - pub(super) fn range_get_ptrs_is_empty( - &self, - range: AllocRange, - cx: &impl HasDataLayout, - ) -> bool { - self.ptrs.range_is_empty(Self::adjusted_range(range, cx)) + /// `pm.range_ptrs_is_empty(r, cx)` == `pm.range_ptrs_get(r, cx).is_empty()`, but is faster. + pub(super) fn range_ptrs_is_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool { + self.ptrs.range_is_empty(Self::adjusted_range_ptrs(range, cx)) } /// Returns all byte-wise provenance in the given range. - fn range_get_bytes(&self, range: AllocRange) -> &[(Size, Prov)] { + fn range_bytes_get(&self, range: AllocRange) -> &[(Size, Prov)] { if let Some(bytes) = self.bytes.as_ref() { bytes.range(range.start..range.end()) } else { @@ -106,9 +101,14 @@ impl ProvenanceMap { } } + /// Same as `range_bytes_get(range).is_empty()`, but faster. + fn range_bytes_is_empty(&self, range: AllocRange) -> bool { + self.bytes.as_ref().is_none_or(|bytes| bytes.range_is_empty(range.start..range.end())) + } + /// Get the provenance of a single byte. pub fn get(&self, offset: Size, cx: &impl HasDataLayout) -> Option { - let prov = self.range_get_ptrs(alloc_range(offset, Size::from_bytes(1)), cx); + let prov = self.range_ptrs_get(alloc_range(offset, Size::from_bytes(1)), cx); debug_assert!(prov.len() <= 1); if let Some(entry) = prov.first() { // If it overlaps with this byte, it is on this byte. @@ -132,7 +132,7 @@ impl ProvenanceMap { /// limit access to provenance outside of the `Allocation` abstraction. /// pub fn range_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool { - self.range_get_ptrs_is_empty(range, cx) && self.range_get_bytes(range).is_empty() + self.range_ptrs_is_empty(range, cx) && self.range_bytes_is_empty(range) } /// Yields all the provenances stored in this map. @@ -164,14 +164,14 @@ impl ProvenanceMap { // provenance that overlaps with the given range. let (first, last) = { // Find all provenance overlapping the given range. - if self.range_get_ptrs_is_empty(range, cx) { + if self.range_ptrs_is_empty(range, cx) { // No provenance in this range, we are done. This is the common case. return Ok(()); } // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much // colder than the early return above, so it's worth it. - let provenance = self.range_get_ptrs(range, cx); + let provenance = self.range_ptrs_get(range, cx); ( provenance.first().unwrap().0, provenance.last().unwrap().0 + cx.data_layout().pointer_size, @@ -284,8 +284,8 @@ impl ProvenanceMap { // This includes the existing bytewise provenance in the range, and ptr provenance // that overlaps with the begin/end of the range. let mut dest_bytes_box = None; - let begin_overlap = self.range_get_ptrs(alloc_range(src.start, Size::ZERO), cx).first(); - let end_overlap = self.range_get_ptrs(alloc_range(src.end(), Size::ZERO), cx).first(); + let begin_overlap = self.range_ptrs_get(alloc_range(src.start, Size::ZERO), cx).first(); + let end_overlap = self.range_ptrs_get(alloc_range(src.end(), Size::ZERO), cx).first(); if !Prov::OFFSET_IS_ADDR { // There can't be any bytewise provenance, and we cannot split up the begin/end overlap. if let Some(entry) = begin_overlap { @@ -308,10 +308,10 @@ impl ProvenanceMap { } else { trace!("no start overlapping entry"); } + // Then the main part, bytewise provenance from `self.bytes`. - if let Some(all_bytes) = self.bytes.as_ref() { - bytes.extend(all_bytes.range(src.start..src.end())); - } + bytes.extend(self.range_bytes_get(src)); + // And finally possibly parts of a pointer at the end. if let Some(entry) = end_overlap { trace!("end overlapping entry: {entry:?}"); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index e5592de81cd78..72f31cec00826 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; -use rustc_macros::{HashStable, TypeVisitable}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -49,10 +49,13 @@ macro_rules! thir_with_elements { } )* + // Note: Making `Thir` implement `Clone` is useful for external tools that need access to + // THIR bodies even after the `Steal` query result has been stolen. + // One such tool is https://github.com/rust-corpus/qrates/. /// A container for a THIR body. /// /// This can be indexed directly by any THIR index (e.g. [`ExprId`]). - #[derive(Debug, HashStable)] + #[derive(Debug, HashStable, Clone)] pub struct Thir<'tcx> { pub body_type: BodyTy<'tcx>, $( @@ -90,7 +93,7 @@ thir_with_elements! { params: ParamId => Param<'tcx> => "p{}", } -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, Clone)] pub enum BodyTy<'tcx> { Const(Ty<'tcx>), Fn(FnSig<'tcx>), @@ -98,7 +101,7 @@ pub enum BodyTy<'tcx> { } /// Description of a type-checked function parameter. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Param<'tcx> { /// The pattern that appears in the parameter list, or None for implicit parameters. pub pat: Option>>, @@ -118,7 +121,7 @@ pub enum LintLevel { Explicit(HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Block { /// Whether the block itself has a label. Used by `label: {}` /// and `try` blocks. @@ -138,7 +141,7 @@ pub struct Block { type UserTy<'tcx> = Option>>; -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct AdtExpr<'tcx> { /// The ADT we're constructing. pub adt_def: AdtDef<'tcx>, @@ -155,7 +158,7 @@ pub struct AdtExpr<'tcx> { pub base: AdtExprBase<'tcx>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum AdtExprBase<'tcx> { /// A struct expression where all the fields are explicitly enumerated: `Foo { a, b }`. None, @@ -168,7 +171,7 @@ pub enum AdtExprBase<'tcx> { DefaultFields(Box<[Ty<'tcx>]>), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct ClosureExpr<'tcx> { pub closure_id: LocalDefId, pub args: UpvarArgs<'tcx>, @@ -177,7 +180,7 @@ pub struct ClosureExpr<'tcx> { pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct InlineAsmExpr<'tcx> { pub asm_macro: AsmMacro, pub template: &'tcx [InlineAsmTemplatePiece], @@ -195,12 +198,12 @@ pub enum BlockSafety { ExplicitUnsafe(HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Stmt<'tcx> { pub kind: StmtKind<'tcx>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum StmtKind<'tcx> { /// An expression with a trailing semicolon. Expr { @@ -240,11 +243,11 @@ pub enum StmtKind<'tcx> { }, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub struct LocalVarId(pub HirId); /// A THIR expression. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { /// kind of expression pub kind: ExprKind<'tcx>, @@ -271,7 +274,7 @@ pub struct TempLifetime { pub backwards_incompatible: Option, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum ExprKind<'tcx> { /// `Scope`s are used to explicitly mark destruction scopes, /// and to track the `HirId` of the expressions within the scope. @@ -548,20 +551,20 @@ pub enum ExprKind<'tcx> { /// Represents the association of a field identifier and an expression. /// /// This is used in struct constructors. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FieldExpr { pub name: FieldIdx, pub expr: ExprId, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FruInfo<'tcx> { pub base: ExprId, pub field_types: Box<[Ty<'tcx>]>, } /// A `match` arm. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Arm<'tcx> { pub pattern: Box>, pub guard: Option, @@ -579,7 +582,7 @@ pub enum LogicalOp { Or, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, @@ -616,13 +619,13 @@ pub enum InlineAsmOperand<'tcx> { }, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct FieldPat<'tcx> { pub field: FieldIdx, pub pattern: Pat<'tcx>, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Pat<'tcx> { pub ty: Ty<'tcx>, pub span: Span, @@ -729,7 +732,7 @@ impl<'tcx> Pat<'tcx> { } } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Ascription<'tcx> { pub annotation: CanonicalUserTypeAnnotation<'tcx>, /// Variance to use when relating the `user_ty` to the **type of the value being @@ -753,7 +756,7 @@ pub struct Ascription<'tcx> { pub variance: ty::Variance, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b8698aa823357..53f233f20eb94 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -397,9 +397,9 @@ pub enum ObligationCauseCode<'tcx> { RustCall, - /// Obligations to prove that a `std::ops::Drop` impl is not stronger than + /// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than /// the ADT it's being implemented for. - DropImpl, + AlwaysApplicableImpl, /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ec0498b168c01..0b8f0e8cd41d9 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -220,13 +220,9 @@ impl FlagComputation { &ty::Pat(ty, pat) => { self.add_ty(ty); match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { - if let Some(start) = start { - self.add_const(start) - } - if let Some(end) = end { - self.add_const(end) - } + ty::PatternKind::Range { start, end } => { + self.add_const(start); + self.add_const(end); } } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 505c7278176f3..953ad62be0a86 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -236,6 +236,11 @@ impl<'tcx> InhabitedPredicate<'tcx> { self.instantiate_opt(tcx, args).unwrap_or(self) } + /// Same as [`Self::instantiate`], but if there is no generics to + /// instantiate, returns `None`. This is useful because it lets us avoid + /// allocating a recursive copy of everything when the result is unchanged. + /// + /// Only used to implement `instantiate` itself. fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option { match self { Self::ConstIsZero(c) => { @@ -260,7 +265,10 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True), Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))), }, - _ => None, + Self::True | Self::False | Self::NotInModule(_) => None, + Self::OpaqueType(_) => { + bug!("unexpected OpaqueType in InhabitedPredicate"); + } } } } diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index e604aedd05e32..4cad1ab209916 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -26,18 +26,30 @@ impl<'tcx> fmt::Debug for Pattern<'tcx> { impl<'tcx> fmt::Debug for PatternKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - PatternKind::Range { start, end, include_end } => { - if let Some(start) = start { - write!(f, "{start}")?; + PatternKind::Range { start, end } => { + write!(f, "{start}")?; + + if let Some(c) = end.try_to_value() { + let end = c.valtree.unwrap_leaf(); + let size = end.size(); + let max = match c.ty.kind() { + ty::Int(_) => { + Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size)) + } + ty::Uint(_) => { + Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size)) + } + ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)), + _ => None, + }; + if let Some((max, _)) = max + && end == max + { + return write!(f, ".."); + } } - write!(f, "..")?; - if include_end { - write!(f, "=")?; - } - if let Some(end) = end { - write!(f, "{end}")?; - } - Ok(()) + + write!(f, "..={end}") } } } @@ -46,5 +58,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> { #[derive(Clone, PartialEq, Eq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum PatternKind<'tcx> { - Range { start: Option>, end: Option>, include_end: bool }, + Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> }, } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 839c1c346a47b..b1dfcb80bde57 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -51,22 +51,12 @@ impl<'tcx> Relate> for ty::Pattern<'tcx> { ) -> RelateResult<'tcx, Self> { match (&*a, &*b) { ( - &ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a }, - &ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b }, + &ty::PatternKind::Range { start: start_a, end: end_a }, + &ty::PatternKind::Range { start: start_b, end: end_b }, ) => { - // FIXME(pattern_types): make equal patterns equal (`0..=` is the same as `..=`). - let mut relate_opt_const = |a, b| match (a, b) { - (None, None) => Ok(None), - (Some(a), Some(b)) => relation.relate(a, b).map(Some), - // FIXME(pattern_types): report a better error - _ => Err(TypeError::Mismatch), - }; - let start = relate_opt_const(start_a, start_b)?; - let end = relate_opt_const(end_a, end_b)?; - if inc_a != inc_b { - todo!() - } - Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a })) + let start = relation.relate(start_a, start_b)?; + let end = relation.relate(end_a, end_b)?; + Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end })) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index db9e9fbc643b2..6c62c04f42e4c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -284,6 +284,7 @@ TrivialTypeTraversalImpls! { rustc_hir::def_id::LocalDefId, rustc_hir::HirId, rustc_hir::MatchSource, + rustc_hir::RangeEnd, rustc_span::Ident, rustc_span::Span, rustc_span::Symbol, diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 3e8a3d1a28923..a23316ae6fc88 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -137,9 +137,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Pat(ty, pat) => { match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { - stack.extend(end.map(Into::into)); - stack.extend(start.map(Into::into)); + ty::PatternKind::Range { start, end } => { + stack.push(end.into()); + stack.push(start.into()); } } stack.push(ty.into()); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3f642a7ac1fdd..c3b1956ad2e82 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2954,14 +2954,27 @@ impl<'a> Parser<'a> { } _ => unreachable!(), }; + // is lifetime `n` tokens ahead? + let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime()); // Is `self` `n` tokens ahead? let is_isolated_self = |this: &Self, n| { this.is_keyword_ahead(n, &[kw::SelfLower]) && this.look_ahead(n + 1, |t| t != &token::PathSep) }; + // Is `pin const self` `n` tokens ahead? + let is_isolated_pin_const_self = |this: &Self, n| { + this.look_ahead(n, |token| token.is_ident_named(sym::pin)) + && this.is_keyword_ahead(n + 1, &[kw::Const]) + && is_isolated_self(this, n + 2) + }; // Is `mut self` `n` tokens ahead? let is_isolated_mut_self = |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1); + // Is `pin mut self` `n` tokens ahead? + let is_isolated_pin_mut_self = |this: &Self, n| { + this.look_ahead(n, |token| token.is_ident_named(sym::pin)) + && is_isolated_mut_self(this, n + 1) + }; // Parse `self` or `self: TYPE`. We already know the current token is `self`. let parse_self_possibly_typed = |this: &mut Self, m| { let eself_ident = expect_self_ident(this); @@ -3012,26 +3025,35 @@ impl<'a> Parser<'a> { let eself_lo = self.token.span; let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind { token::And => { - let eself = if is_isolated_self(self, 1) { - // `&self` - self.bump(); - SelfKind::Region(None, Mutability::Not) - } else if is_isolated_mut_self(self, 1) { - // `&mut self` - self.bump(); - self.bump(); - SelfKind::Region(None, Mutability::Mut) - } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { - // `&'lt self` - self.bump(); - let lt = self.expect_lifetime(); - SelfKind::Region(Some(lt), Mutability::Not) - } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { - // `&'lt mut self` - self.bump(); - let lt = self.expect_lifetime(); - self.bump(); - SelfKind::Region(Some(lt), Mutability::Mut) + let has_lifetime = is_lifetime(self, 1); + let skip_lifetime_count = has_lifetime as usize; + let eself = if is_isolated_self(self, skip_lifetime_count + 1) { + // `&{'lt} self` + self.bump(); // & + let lifetime = has_lifetime.then(|| self.expect_lifetime()); + SelfKind::Region(lifetime, Mutability::Not) + } else if is_isolated_mut_self(self, skip_lifetime_count + 1) { + // `&{'lt} mut self` + self.bump(); // & + let lifetime = has_lifetime.then(|| self.expect_lifetime()); + self.bump(); // mut + SelfKind::Region(lifetime, Mutability::Mut) + } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) { + // `&{'lt} pin const self` + self.bump(); // & + let lifetime = has_lifetime.then(|| self.expect_lifetime()); + self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span); + self.bump(); // pin + self.bump(); // const + SelfKind::Pinned(lifetime, Mutability::Not) + } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) { + // `&{'lt} pin mut self` + self.bump(); // & + let lifetime = has_lifetime.then(|| self.expect_lifetime()); + self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span); + self.bump(); // pin + self.bump(); // mut + SelfKind::Pinned(lifetime, Mutability::Mut) } else { // `¬_self` return Ok(None); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 29b606b7a5909..92f5fba1f9b9a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -624,7 +624,7 @@ pub(crate) struct UnnecessaryQualification<'ra> { pub removal_span: Span, } -#[derive(Default)] +#[derive(Default, Debug)] struct DiagMetadata<'ast> { /// The current trait's associated items' ident, used for diagnostic suggestions. current_trait_assoc_items: Option<&'ast [P]>, @@ -3147,6 +3147,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathSource::Trait(AliasPossibility::No), Finalize::new(trait_ref.ref_id, trait_ref.path.span), RecordPartialRes::Yes, + None, ); self.diag_metadata.currently_processing_impl_trait = None; if let Some(def_id) = res.expect_full_res().opt_def_id() { @@ -4073,6 +4074,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { source, Finalize::new(id, path.span), RecordPartialRes::Yes, + None, ); } @@ -4084,14 +4086,21 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { source: PathSource<'ast>, finalize: Finalize, record_partial_res: RecordPartialRes, + parent_qself: Option<&QSelf>, ) -> PartialRes { let ns = source.namespace(); let Finalize { node_id, path_span, .. } = finalize; let report_errors = |this: &mut Self, res: Option| { if this.should_report_errs() { - let (err, candidates) = - this.smart_resolve_report_errors(path, None, path_span, source, res); + let (err, candidates) = this.smart_resolve_report_errors( + path, + None, + path_span, + source, + res, + parent_qself, + ); let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); @@ -4160,6 +4169,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { path_span, PathSource::Type, None, + parent_qself, ); // There are two different error messages user might receive at @@ -4437,6 +4447,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathSource::Trait(AliasPossibility::No), Finalize::new(finalize.node_id, qself.path_span), RecordPartialRes::No, + Some(&qself), ); if trait_res.expect_full_res() == Res::Err { @@ -4461,6 +4472,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathSource::TraitItem(ns), Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), RecordPartialRes::No, + Some(&qself), ); // The remaining segments (the `C` in our example) will diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 42be92c0f8fe5..67024f988a452 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -35,7 +35,7 @@ use super::NoConstantGenericsReason; use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion}; use crate::late::{ AliasPossibility, LateResolutionVisitor, LifetimeBinderKind, LifetimeRes, LifetimeRibKind, - LifetimeUseSet, RibKind, + LifetimeUseSet, QSelf, RibKind, }; use crate::ty::fast_reject::SimplifiedType; use crate::{ @@ -421,6 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: Span, source: PathSource<'_>, res: Option, + qself: Option<&QSelf>, ) -> (Diag<'tcx>, Vec) { debug!(?res, ?source); let base_error = self.make_base_error(path, span, source, res); @@ -429,6 +430,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone()); err.code(code); + // Try to get the span of the identifier within the path's syntax context + // (if that's different). + if let Some(within_macro_span) = + base_error.span.within_macro(span, self.r.tcx.sess.source_map()) + { + err.span_label(within_macro_span, "due to this macro variable"); + } + self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); @@ -453,6 +462,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { self.suggest_self_or_self_ref(&mut err, path, span); self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error); + self.detect_rtn_with_fully_qualified_path( + &mut err, + path, + following_seg, + span, + source, + res, + qself, + ); if self.suggest_self_ty(&mut err, source, path, span) || self.suggest_self_value(&mut err, source, path, span) { @@ -501,6 +519,33 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { (err, candidates) } + fn detect_rtn_with_fully_qualified_path( + &self, + err: &mut Diag<'_>, + path: &[Segment], + following_seg: Option<&Segment>, + span: Span, + source: PathSource<'_>, + res: Option, + qself: Option<&QSelf>, + ) { + if let Some(Res::Def(DefKind::AssocFn, _)) = res + && let PathSource::TraitItem(TypeNS) = source + && let None = following_seg + && let Some(qself) = qself + && let TyKind::Path(None, ty_path) = &qself.ty.kind + && ty_path.segments.len() == 1 + && self.diag_metadata.current_where_predicate.is_some() + { + err.span_suggestion_verbose( + span, + "you might have meant to use the return type notation syntax", + format!("{}::{}(..)", ty_path.segments[0].ident, path[path.len() - 1].ident), + Applicability::MaybeIncorrect, + ); + } + } + fn detect_assoc_type_constraint_meant_as_path( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 50cf605ba2a82..bb2b2dea2f37f 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -88,10 +88,9 @@ impl RustcInternal for Pattern { type T<'tcx> = rustc_ty::Pattern<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { tcx.mk_pat(match self { - Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range { - start: start.as_ref().map(|c| c.internal(tables, tcx)), - end: end.as_ref().map(|c| c.internal(tables, tcx)), - include_end: *include_end, + Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range { + start: start.as_ref().unwrap().internal(tables, tcx), + end: end.as_ref().unwrap().internal(tables, tcx), }, }) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index a0faf20c79a67..aa0eac628dd0f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -405,10 +405,11 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { match **self { - ty::PatternKind::Range { start, end, include_end } => stable_mir::ty::Pattern::Range { - start: start.stable(tables), - end: end.stable(tables), - include_end, + ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range { + // FIXME(SMIR): update data structures to not have an Option here anymore + start: Some(start.stable(tables)), + end: Some(end.stable(tables)), + include_end: true, }, } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 84e89ff4b7dab..64982b858c644 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1173,6 +1173,8 @@ pub enum DesugaringKind { BoundModifier, /// Calls to contract checks (`#[requires]` to precond, `#[ensures]` to postcond) Contract, + /// A pattern type range start/end + PatTyRange, } impl DesugaringKind { @@ -1190,6 +1192,7 @@ impl DesugaringKind { DesugaringKind::WhileLoop => "`while` loop", DesugaringKind::BoundModifier => "trait bound modifier", DesugaringKind::Contract => "contract check", + DesugaringKind::PatTyRange => "pattern type", } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index bca9323a50d4c..798e186a94b1a 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1057,6 +1057,37 @@ impl Span { } } + /// Returns the `Span` within the syntax context of "within". This is useful when + /// "self" is an expansion from a macro variable, since this can be used for + /// providing extra macro expansion context for certain errors. + /// + /// ```text + /// macro_rules! m { + /// ($ident:ident) => { ($ident,) } + /// } + /// + /// m!(outer_ident); + /// ``` + /// + /// If "self" is the span of the outer_ident, and "within" is the span of the `($ident,)` + /// expr, then this will return the span of the `$ident` macro variable. + pub fn within_macro(self, within: Span, sm: &SourceMap) -> Option { + match Span::prepare_to_combine(self, within) { + // Only return something if it doesn't overlap with the original span, + // and the span isn't "imported" (i.e. from unavailable sources). + // FIXME: This does limit the usefulness of the error when the macro is + // from a foreign crate; we could also take into account `-Zmacro-backtrace`, + // which doesn't redact this span (but that would mean passing in even more + // args to this function, lol). + Ok((self_, _, parent)) + if self_.hi < self.lo() || self.hi() < self_.lo && !sm.is_imported(within) => + { + Some(Span::new(self_.lo, self_.hi, self_.ctxt, parent)) + } + _ => None, + } + } + pub fn from_inner(self, inner: InnerSpan) -> Span { let span = self.data(); Span::new( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 522bccb1acb05..573c65a772cb6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -308,6 +308,9 @@ symbols! { RangeFull, RangeInclusive, RangeInclusiveCopy, + RangeMax, + RangeMin, + RangeSub, RangeTo, RangeToInclusive, Rc, @@ -1522,6 +1525,7 @@ symbols! { pattern_complexity_limit, pattern_parentheses, pattern_type, + pattern_type_range_trait, pattern_types, permissions_from_mode, phantom_data, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index a11f6f0df1c58..bc3923e4b4d67 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -413,12 +413,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } ty::Pat(ty, pat) => match *pat { - ty::PatternKind::Range { start, end, include_end } => { - let consts = [ - start.unwrap_or(self.tcx.consts.unit), - end.unwrap_or(self.tcx.consts.unit), - ty::Const::from_bool(self.tcx, include_end), - ]; + ty::PatternKind::Range { start, end } => { + let consts = [start, end]; // HACK: Represent as tuple until we have something better. // HACK: constants are used in arrays, even if the types don't match. self.push("T"); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index f15f1b78b5282..d673e5672a00b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -1,8 +1,6 @@ use std::ops::ControlFlow; -use rustc_errors::{ - Applicability, Diag, E0283, E0284, E0790, MultiSpan, StashKey, struct_span_code_err, -}; +use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def::{DefKind, Res}; @@ -197,7 +195,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // be ignoring the fact that we don't KNOW the type works // out. Though even that would probably be harmless, given that // we're only talking about builtin traits, which are known to be - // inhabited. We used to check for `self.tcx.sess.has_errors()` to + // inhabited. We used to check for `self.tainted_by_errors()` to // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and don't add the obligations to // begin with in those cases. @@ -211,7 +209,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeAnnotationNeeded::E0282, false, ); - return err.stash(span, StashKey::MaybeForgetReturn).unwrap(); + return err.emit(); } Some(e) => return e, } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 8c1df9b511390..e2bdd52ba7c80 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -829,7 +829,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let ty::Closure(closure_def_id, _) | ty::CoroutineClosure(closure_def_id, _) = *typeck_results.node_type(arg_hir_id).kind() { - // Otherwise, extract the closure kind from the obligation. + // Otherwise, extract the closure kind from the obligation, + // but only if we actually have an argument to deduce the + // closure type from... let mut err = self.report_closure_error( &obligation, closure_def_id, @@ -844,63 +846,72 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let self_ty = trait_pred.self_ty().skip_binder(); - if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) { - let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() { - ty::Closure(def_id, args) => { - (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) - } - ty::CoroutineClosure(def_id, args) => ( - def_id, - args.as_coroutine_closure() - .coroutine_closure_sig() - .map_bound(|sig| sig.tupled_inputs_ty), - Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), - ), - _ => return None, + let (expected_kind, trait_prefix) = + if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) { + (expected_kind, "") + } else if let Some(expected_kind) = + self.tcx.async_fn_trait_kind_from_def_id(trait_pred.def_id()) + { + (expected_kind, "Async") + } else { + return None; }; - let expected_args = - trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1)); - - // Verify that the arguments are compatible. If the signature is - // mismatched, then we have a totally different error to report. - if self.enter_forall(found_args, |found_args| { - self.enter_forall(expected_args, |expected_args| { - !self.can_eq(obligation.param_env, expected_args, found_args) - }) - }) { - return None; + let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() { + ty::Closure(def_id, args) => { + (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) } + ty::CoroutineClosure(def_id, args) => ( + def_id, + args.as_coroutine_closure() + .coroutine_closure_sig() + .map_bound(|sig| sig.tupled_inputs_ty), + Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), + ), + _ => return None, + }; - if let Some(found_kind) = self.closure_kind(self_ty) - && !found_kind.extends(expected_kind) - { - let mut err = self.report_closure_error( - &obligation, - closure_def_id, - found_kind, - expected_kind, - "", - ); - self.note_obligation_cause(&mut err, &obligation); - return Some(err.emit()); - } + let expected_args = trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1)); - // If the closure has captures, then perhaps the reason that the trait - // is unimplemented is because async closures don't implement `Fn`/`FnMut` - // if they have captures. - if let Some(by_ref_captures) = by_ref_captures - && let ty::FnPtr(sig_tys, _) = by_ref_captures.kind() - && !sig_tys.skip_binder().output().is_unit() - { - let mut err = self.dcx().create_err(AsyncClosureNotFn { - span: self.tcx.def_span(closure_def_id), - kind: expected_kind.as_str(), - }); - self.note_obligation_cause(&mut err, &obligation); - return Some(err.emit()); - } + // Verify that the arguments are compatible. If the signature is + // mismatched, then we have a totally different error to report. + if self.enter_forall(found_args, |found_args| { + self.enter_forall(expected_args, |expected_args| { + !self.can_eq(obligation.param_env, expected_args, found_args) + }) + }) { + return None; } + + if let Some(found_kind) = self.closure_kind(self_ty) + && !found_kind.extends(expected_kind) + { + let mut err = self.report_closure_error( + &obligation, + closure_def_id, + found_kind, + expected_kind, + trait_prefix, + ); + self.note_obligation_cause(&mut err, &obligation); + return Some(err.emit()); + } + + // If the closure has captures, then perhaps the reason that the trait + // is unimplemented is because async closures don't implement `Fn`/`FnMut` + // if they have captures. + if let Some(by_ref_captures) = by_ref_captures + && let ty::FnPtr(sig_tys, _) = by_ref_captures.kind() + && !sig_tys.skip_binder().output().is_unit() + { + let mut err = self.dcx().create_err(AsyncClosureNotFn { + span: self.tcx.def_span(closure_def_id), + kind: expected_kind.as_str(), + }); + self.note_obligation_cause(&mut err, &obligation); + return Some(err.emit()); + } + None } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d180c0be9d5a7..ad46a15a5ac6d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2695,7 +2695,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::LetElse | ObligationCauseCode::BinOp { .. } | ObligationCauseCode::AscribeUserTypeProvePredicate(..) - | ObligationCauseCode::DropImpl + | ObligationCauseCode::AlwaysApplicableImpl | ObligationCauseCode::ConstParam(_) | ObligationCauseCode::ReferenceOutlivesReferent(..) | ObligationCauseCode::ObjectTypeBound(..) => {} @@ -3191,7 +3191,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { false }; - if !is_upvar_tys_infer_tuple { + let is_builtin_async_fn_trait = + tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some(); + + if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait { let ty_str = tcx.short_string(ty, err.long_ty_path()); let msg = format!("required because it appears within the type `{ty_str}`"); match ty.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 6669d8525fa4f..6db97fc321a8d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -983,8 +983,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(SelectionError::Unimplemented); } } else { - nested.push(obligation.with( + nested.push(Obligation::new( self.tcx(), + obligation.derived_cause(ObligationCauseCode::BuiltinDerived), + obligation.param_env, ty::TraitRef::new( self.tcx(), self.tcx().require_lang_item( diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 18906a6a8ce0f..54b6c22b2d821 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -708,7 +708,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::Pat(subty, pat) => { self.require_sized(subty, ObligationCauseCode::Misc); match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { + ty::PatternKind::Range { start, end } => { let mut check = |c| { let cause = self.cause(ObligationCauseCode::Misc); self.out.push(traits::Obligation::with_depth( @@ -738,12 +738,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } } }; - if let Some(start) = start { - check(start) - } - if let Some(end) = end { - check(end) - } + check(start); + check(end); } } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 852d3fc58d879..a53f0538c5816 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -205,24 +205,17 @@ fn layout_of_uncached<'tcx>( let layout = cx.layout_of(ty)?.layout; let mut layout = LayoutData::clone(&layout.0); match *pat { - ty::PatternKind::Range { start, end, include_end } => { + ty::PatternKind::Range { start, end } => { if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = &mut layout.backend_repr { - if let Some(start) = start { - scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? - .try_to_bits(tcx, cx.typing_env) - .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; - } - if let Some(end) = end { - let mut end = extract_const_value(cx, ty, end)? - .try_to_bits(tcx, cx.typing_env) - .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; - if !include_end { - end = end.wrapping_sub(1); - } - scalar.valid_range_mut().end = end; - } + scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? + .try_to_bits(tcx, cx.typing_env) + .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; + + scalar.valid_range_mut().end = extract_const_value(cx, ty, end)? + .try_to_bits(tcx, cx.typing_env) + .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; let niche = Niche { offset: Size::ZERO, diff --git a/library/Cargo.lock b/library/Cargo.lock index efb6b83a093ec..316564141216e 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.150" +version = "0.1.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c42734e0ccf0d9f953165770593a75306f0b24dda1aa03f115c70748726dbca" +checksum = "abc30f1766d387c35f2405e586d3e7a88230dc728ff78cd1d0bc59ae0b63154b" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 9cf9e98e89ee4..4cb8350125686 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.9.0", default-features = false, features = ["alloc"] } diff --git a/library/core/src/bstr.rs b/library/core/src/bstr.rs index 74e07f3d242cd..ae84fd8adb61c 100644 --- a/library/core/src/bstr.rs +++ b/library/core/src/bstr.rs @@ -151,7 +151,9 @@ impl fmt::Display for ByteStr { }; let nchars: usize = self .utf8_chunks() - .map(|chunk| chunk.valid().len() + if chunk.invalid().is_empty() { 0 } else { 1 }) + .map(|chunk| { + chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 } + }) .sum(); let padding = f.width().unwrap_or(0).saturating_sub(nchars); let fill = f.fill(); diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index e468f4f0f7e66..43fd54f881dae 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -778,7 +778,6 @@ impl From for T { /// /// [#64715]: https://github.com/rust-lang/rust/issues/64715 #[stable(feature = "convert_infallible", since = "1.34.0")] -#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead. #[rustc_reservation_impl = "permitting this impl would forbid us from adding \ `impl From for T` later; see rust-lang/rust#64715 for details"] impl From for T { diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs index e14c9235e5562..5466131903f85 100644 --- a/library/core/src/iter/sources/successors.rs +++ b/library/core/src/iter/sources/successors.rs @@ -1,11 +1,16 @@ use crate::fmt; use crate::iter::FusedIterator; -/// Creates a new iterator where each successive item is computed based on the preceding one. +/// Creates an iterator which, starting from an initial item, +/// computes each successive item from the preceding one. /// -/// The iterator starts with the given first item (if any) -/// and calls the given `FnMut(&T) -> Option` closure to compute each item’s successor. -/// The iterator will yield the `T`s returned from the closure. +/// This iterator stores an optional item (`Option`) and a successor closure (`impl FnMut(&T) -> Option`). +/// Its `next` method returns the stored optional item and +/// if it is `Some(val)` calls the stored closure on `&val` to compute and store its successor. +/// The iterator will apply the closure successively to the stored option's value until the option is `None`. +/// This also means that once the stored option is `None` it will remain `None`, +/// as the closure will not be called again, so the created iterator is a [`FusedIterator`]. +/// The iterator's items will be the initial item and all of its successors as calculated by the successor closure. /// /// ``` /// use std::iter::successors; @@ -24,7 +29,8 @@ where Successors { next: first, succ } } -/// A new iterator where each successive item is computed based on the preceding one. +/// An iterator which, starting from an initial item, +/// computes each successive item from the preceding one. /// /// This `struct` is created by the [`iter::successors()`] function. /// See its documentation for more. diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index b0571bf7247af..e2dd813981d04 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -453,8 +453,8 @@ impl Copy for ! {} #[stable(feature = "rust1", since = "1.0.0")] impl Copy for &T {} -/// Marker trait for the types that are allowed in union fields, unsafe fields, -/// and unsafe binder types. +/// Marker trait for the types that are allowed in union fields and unsafe +/// binder types. /// /// Implemented for: /// * `&T`, `&mut T` for all `T`, diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index 752e79c2dacee..f8826096df3e1 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -12,3 +12,65 @@ macro_rules! pattern_type { /* compiler built-in */ }; } + +/// A trait implemented for integer types and `char`. +/// Useful in the future for generic pattern types, but +/// used right now to simplify ast lowering of pattern type ranges. +#[unstable(feature = "pattern_type_range_trait", issue = "123646")] +#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")] +#[const_trait] +#[diagnostic::on_unimplemented( + message = "`{Self}` is not a valid base type for range patterns", + label = "only integer types and `char` are supported" +)] +pub trait RangePattern { + /// Trait version of the inherent `MIN` assoc const. + #[cfg_attr(not(bootstrap), lang = "RangeMin")] + const MIN: Self; + + /// Trait version of the inherent `MIN` assoc const. + #[cfg_attr(not(bootstrap), lang = "RangeMax")] + const MAX: Self; + + /// A compile-time helper to subtract 1 for exclusive ranges. + #[cfg_attr(not(bootstrap), lang = "RangeSub")] + #[track_caller] + fn sub_one(self) -> Self; +} + +macro_rules! impl_range_pat { + ($($ty:ty,)*) => { + $( + #[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")] + impl const RangePattern for $ty { + const MIN: $ty = <$ty>::MIN; + const MAX: $ty = <$ty>::MAX; + fn sub_one(self) -> Self { + match self.checked_sub(1) { + Some(val) => val, + None => panic!("exclusive range end at minimum value of type") + } + } + } + )* + } +} + +impl_range_pat! { + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize, +} + +#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")] +impl const RangePattern for char { + const MIN: Self = char::MIN; + + const MAX: Self = char::MAX; + + fn sub_one(self) -> Self { + match char::from_u32(self as u32 - 1) { + None => panic!("exclusive range to start of valid chars"), + Some(val) => val, + } + } +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f762d20546311..0ec167c2d1618 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.150" } +compiler_builtins = { version = "=0.1.151" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 4a071b4e1faec..e62aeb2ede0ad 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -641,11 +641,6 @@ impl Error for JoinPathsError { /// None => println!("Impossible to get your home dir!"), /// } /// ``` -#[deprecated( - since = "1.29.0", - note = "This function's behavior may be unexpected on Windows. \ - Consider using a crate from crates.io instead." -)] #[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn home_dir() -> Option { diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index bbcc01a0c2998..6b88c26e3a276 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -54,7 +54,7 @@ runners: <<: *base-job - &job-aarch64-linux-8c - os: ubuntu-22.04-arm64-8core-32gb + os: ubuntu-24.04-arm64-8core-32gb <<: *base-job envs: env-x86_64-apple-tests: &env-x86_64-apple-tests diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d9c2f6b28a79d..b1d7e5421c1b4 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -69,6 +69,7 @@ - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md) + - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md) - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md) - [powerpc64-ibm-aix](platform-support/aix.md) - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index dd085f916b911..84440a5ab78b0 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -348,9 +348,9 @@ target | std | host | notes [`mipsisa64r6el-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ✓ | ✓ | 64-bit MIPS Release 6 Little Endian `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers [`powerpc-unknown-freebsd`](platform-support/freebsd.md) | ? | | PowerPC FreeBSD -`powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux +[`powerpc-unknown-linux-gnuspe`](platform-support/powerpc-unknown-linux-gnuspe.md) | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3 -[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux +[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux with musl 1.2.3 [`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems [`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | | [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | diff --git a/src/doc/rustc/src/platform-support/powerpc-unknown-linux-gnuspe.md b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-gnuspe.md new file mode 100644 index 0000000000000..a9983a141115f --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-gnuspe.md @@ -0,0 +1,20 @@ +# powerpc-unknown-linux-gnuspe + +**Tier: 3** + +`powerpc-unknown-linux-gnuspe` is a target for Linux on 32-bit PowerPC +processors that implement the Signal Processing Engine (SPE), such as e500, and +uses a different ABI than standard `powerpc-unknown-linux-gnu`. +When building for other 32-bit PowerPC processors, use +`powerpc-unknown-linux-gnu` instead. + +See also [Debian Wiki](https://wiki.debian.org/PowerPCSPEPort) for details on +this platform, and [ABI reference](https://web.archive.org/web/20120608163804/https://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf) +for details on SPE ABI. + +Note that support for PowerPC SPE by GCC was [removed in GCC 9](https://gcc.gnu.org/gcc-8/changes.html), +so recent GCC cannot be used as linker/compiler for this target. + +## Target maintainers + +There are currently no formally documented target maintainers. diff --git a/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md index 4c416b5192994..6b62e9ddba109 100644 --- a/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md +++ b/src/doc/rustc/src/platform-support/powerpc-unknown-linux-muslspe.md @@ -2,9 +2,11 @@ **Tier: 3** -This target is very similar to already existing ones like `powerpc_unknown_linux_musl` and `powerpc_unknown_linux_gnuspe`. +This target is very similar to already existing ones like `powerpc-unknown-linux-musl` and `powerpc-unknown-linux-gnuspe`. This one has PowerPC SPE support for musl. Unfortunately, the last supported gcc version with PowerPC SPE is 8.4.0. +See also [platform support documentation of `powerpc-unknown-linux-gnuspe`](powerpc-unknown-linux-gnuspe.md) for information about PowerPC SPE. + ## Target maintainers - [@BKPepe](https://github.com/BKPepe) diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md index bfdb579cd3523..b2f59732801bc 100644 --- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md @@ -9,12 +9,32 @@ The tracking issue for this feature is: [#123076] This feature is incomplete and not yet intended for general use. This implements experimental, Edition-dependent match ergonomics under consideration for inclusion -in Rust. -For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for -[Editions 2024 and later]. +in Rust, allowing `&` patterns in more places. For example: +```rust,edition2024 +#![feature(ref_pat_eat_one_layer_2024_structural)] +#![allow(incomplete_features)] +# +# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`. +# trait Eq {} +# impl Eq for T {} +# fn has_type(_: impl Eq) {} + +// `&` can match against a `ref` binding mode instead of a reference type: +let (x, &y) = &(0, 1); +has_type::<&u8>(x); +has_type::(y); + +// `&` can match against `&mut` references: +let &z = &mut 2; +has_type::(z); +``` + +For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for +[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference]. For alternative experimental match ergonomics, see the feature [`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md). [Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false +[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md index 0c90cec0dbddb..f7c85eec2d28e 100644 --- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md @@ -9,12 +9,33 @@ The tracking issue for this feature is: [#123076] This feature is incomplete and not yet intended for general use. This implements experimental, Edition-dependent match ergonomics under consideration for inclusion -in Rust. -For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for -[Editions 2024 and later]. +in Rust, allowing `&` patterns in more places. For example: + +```rust,edition2024 +#![feature(ref_pat_eat_one_layer_2024)] +#![allow(incomplete_features)] +# +# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`. +# trait Eq {} +# impl Eq for T {} +# fn has_type(_: impl Eq) {} + +// `&` can match against a `ref` binding mode instead of a reference type: +let (x, &y) = &(0, 1); +has_type::<&u8>(x); +has_type::(y); + +// `&` can match against `&mut` references: +let &z = &mut 2; +has_type::(z); +``` + +For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for +[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference]. For alternative experimental match ergonomics, see the feature [`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md). [Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false +[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index a71bb62e56c74..bcdca862862d4 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -7,9 +7,8 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; use tracing::debug; -use crate::clean; use crate::clean::utils::inherits_doc_hidden; -use crate::clean::{Item, ItemIdSet}; +use crate::clean::{self, Item, ItemIdSet, reexport_chain}; use crate::core::DocContext; use crate::fold::{DocFolder, strip_item}; use crate::passes::{ImplStripper, Pass}; @@ -89,6 +88,25 @@ impl Stripper<'_, '_> { impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.is_doc_hidden(); + + if let clean::ImportItem(clean::Import { source, .. }) = &i.kind + && let Some(source_did) = source.did + && let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) + { + let reexports = reexport_chain(self.tcx, import_def_id, source_did); + + // Check if any reexport in the chain has a hidden source + let has_hidden_source = reexports + .iter() + .filter_map(|reexport| reexport.id()) + .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)) + || self.tcx.is_doc_hidden(source_did); + + if has_hidden_source { + return None; + } + } + let is_impl_or_exported_macro = match i.kind { clean::ImplItem(..) => true, // If the macro has the `#[macro_export]` attribute, it means it's accessible at the diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 4bd86a2533518..c47c08285c2eb 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1108,14 +1108,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { - TyPatKind::Range(s, e, i) => { - if let Some(s) = s { - self.hash_const_arg(s); - } - if let Some(e) = e { - self.hash_const_arg(e); - } - std::mem::discriminant(&i).hash(&mut self.s); + TyPatKind::Range(s, e) => { + self.hash_const_arg(s); + self.hash_const_arg(e); }, TyPatKind::Err(_) => {}, } diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index a4f2a117b181c..ff3a25e94bd5d 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -285,9 +285,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn expose_ptr(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { + fn expose_provenance(&self, provenance: Provenance) -> InterpResult<'tcx> { let this = self.eval_context_ref(); let mut global_state = this.machine.alloc_addresses.borrow_mut(); + + let (alloc_id, tag) = match provenance { + Provenance::Concrete { alloc_id, tag } => (alloc_id, tag), + Provenance::Wildcard => { + // No need to do anything for wildcard pointers as + // their provenances have already been previously exposed. + return interp_ok(()); + } + }; + // In strict mode, we don't need this, so we can save some cycles by not tracking it. if global_state.provenance_mode == ProvenanceMode::Strict { return interp_ok(()); @@ -422,6 +432,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let rel_offset = this.truncate_to_target_usize(addr.bytes().wrapping_sub(base_addr)); Some((alloc_id, Size::from_bytes(rel_offset))) } + + /// Prepare all exposed memory for a native call. + /// This overapproximates the modifications which external code might make to memory: + /// We set all reachable allocations as initialized, mark all reachable provenances as exposed + /// and overwrite them with `Provenance::WILDCARD`. + fn prepare_exposed_for_native_call(&mut self) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + // We need to make a deep copy of this list, but it's fine; it also serves as scratch space + // for the search within `prepare_for_native_call`. + let exposed: Vec = + this.machine.alloc_addresses.get_mut().exposed.iter().copied().collect(); + this.prepare_for_native_call(exposed) + } } impl<'tcx> MiriMachine<'tcx> { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 4ece8f7895dee..dbb092f67286a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1291,18 +1291,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { /// Called on `ptr as usize` casts. /// (Actually computing the resulting `usize` doesn't need machine help, /// that's just `Scalar::try_to_int`.) + #[inline(always)] fn expose_provenance( ecx: &InterpCx<'tcx, Self>, provenance: Self::Provenance, ) -> InterpResult<'tcx> { - match provenance { - Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag), - Provenance::Wildcard => { - // No need to do anything for wildcard pointers as - // their provenances have already been previously exposed. - interp_ok(()) - } - } + ecx.expose_provenance(provenance) } /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info. diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index 8c9e1860f31d9..c6fcb0355eb80 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -160,16 +160,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let imm = this.read_immediate(arg)?; libffi_args.push(imm_to_carg(&imm, this)?); - // If we are passing a pointer, prepare the memory it points to. + // If we are passing a pointer, expose its provenance. Below, all exposed memory + // (previously exposed and new exposed) will then be properly prepared. if matches!(arg.layout.ty.kind(), ty::RawPtr(..)) { let ptr = imm.to_scalar().to_pointer(this)?; let Some(prov) = ptr.provenance else { - // Pointer without provenance may not access any memory. - continue; - }; - // We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance. - let Some(alloc_id) = prov.get_alloc_id() else { - // Wildcard pointer, whatever it points to must be already exposed. + // Pointer without provenance may not access any memory anyway, skip. continue; }; // The first time this happens, print a warning. @@ -178,12 +174,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem); } - this.prepare_for_native_call(alloc_id, prov)?; + this.expose_provenance(prov)?; } } - // FIXME: In the future, we should also call `prepare_for_native_call` on all previously - // exposed allocations, since C may access any of them. + // Prepare all exposed memory. + this.prepare_exposed_for_native_call()?; // Convert them to `libffi::high::Arg` type. let libffi_args = libffi_args diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs index a92e63a4da6d8..bd4e0b23601f1 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs @@ -6,7 +6,7 @@ #![feature(box_as_ptr)] use std::mem::MaybeUninit; -use std::ptr::null; +use std::ptr; fn main() { test_increment_int(); @@ -20,6 +20,8 @@ fn main() { test_pass_dangling(); test_swap_ptr_triple_dangling(); test_return_ptr(); + test_pass_ptr_as_int(); + test_pass_ptr_via_previously_shared_mem(); } /// Test function that modifies an int. @@ -112,7 +114,7 @@ fn test_swap_ptr() { } let x = 61; - let (mut ptr0, mut ptr1) = (&raw const x, null()); + let (mut ptr0, mut ptr1) = (&raw const x, ptr::null()); unsafe { swap_ptr(&mut ptr0, &mut ptr1) }; assert_eq!(unsafe { *ptr1 }, x); @@ -131,7 +133,7 @@ fn test_swap_ptr_tuple() { } let x = 71; - let mut tuple = Tuple { ptr0: &raw const x, ptr1: null() }; + let mut tuple = Tuple { ptr0: &raw const x, ptr1: ptr::null() }; unsafe { swap_ptr_tuple(&mut tuple) } assert_eq!(unsafe { *tuple.ptr1 }, x); @@ -148,7 +150,7 @@ fn test_overwrite_dangling() { drop(b); unsafe { overwrite_ptr(&mut ptr) }; - assert_eq!(ptr, null()); + assert_eq!(ptr, ptr::null()); } /// Test function that passes a dangling pointer. @@ -200,3 +202,33 @@ fn test_return_ptr() { let ptr = unsafe { return_ptr(ptr) }; assert_eq!(unsafe { *ptr }, x); } + +/// Test casting a pointer to an integer and passing that to C. +fn test_pass_ptr_as_int() { + extern "C" { + fn pass_ptr_as_int(ptr: usize, set_to_val: i32); + } + + let mut m: MaybeUninit = MaybeUninit::uninit(); + unsafe { pass_ptr_as_int(m.as_mut_ptr() as usize, 42) }; + assert_eq!(unsafe { m.assume_init() }, 42); +} + +fn test_pass_ptr_via_previously_shared_mem() { + extern "C" { + fn set_shared_mem(ptr: *mut *mut i32); + fn init_ptr_stored_in_shared_mem(val: i32); + } + + let mut m: *mut i32 = ptr::null_mut(); + let ptr_to_m = &raw mut m; + unsafe { set_shared_mem(&raw mut m) }; + + let mut m2: MaybeUninit = MaybeUninit::uninit(); + // Store a pointer to m2 somewhere that C code can access it. + unsafe { ptr_to_m.write(m2.as_mut_ptr()) }; + // Have C code write there. + unsafe { init_ptr_stored_in_shared_mem(42) }; + // Ensure this memory is now considered initialized. + assert_eq!(unsafe { m2.assume_init() }, 42); +} diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c index 3b427d6033e3d..b89126d3d7c88 100644 --- a/src/tools/miri/tests/native-lib/ptr_read_access.c +++ b/src/tools/miri/tests/native-lib/ptr_read_access.c @@ -1,33 +1,34 @@ #include +#include // See comments in build_native_lib() #define EXPORT __attribute__((visibility("default"))) /* Test: test_access_pointer */ -EXPORT void print_pointer(const int *ptr) { +EXPORT void print_pointer(const int32_t *ptr) { printf("printing pointer dereference from C: %d\n", *ptr); } /* Test: test_access_simple */ typedef struct Simple { - int field; + int32_t field; } Simple; -EXPORT int access_simple(const Simple *s_ptr) { +EXPORT int32_t access_simple(const Simple *s_ptr) { return s_ptr->field; } /* Test: test_access_nested */ typedef struct Nested { - int value; + int32_t value; struct Nested *next; } Nested; // Returns the innermost/last value of a Nested pointer chain. -EXPORT int access_nested(const Nested *n_ptr) { +EXPORT int32_t access_nested(const Nested *n_ptr) { // Edge case: `n_ptr == NULL` (i.e. first Nested is None). if (!n_ptr) { return 0; } @@ -41,10 +42,10 @@ EXPORT int access_nested(const Nested *n_ptr) { /* Test: test_access_static */ typedef struct Static { - int value; + int32_t value; struct Static *recurse; } Static; -EXPORT int access_static(const Static *s_ptr) { +EXPORT int32_t access_static(const Static *s_ptr) { return s_ptr->recurse->recurse->value; } diff --git a/src/tools/miri/tests/native-lib/ptr_write_access.c b/src/tools/miri/tests/native-lib/ptr_write_access.c index b54c5d86b210d..fd8b005499c76 100644 --- a/src/tools/miri/tests/native-lib/ptr_write_access.c +++ b/src/tools/miri/tests/native-lib/ptr_write_access.c @@ -1,23 +1,24 @@ #include +#include // See comments in build_native_lib() #define EXPORT __attribute__((visibility("default"))) /* Test: test_increment_int */ -EXPORT void increment_int(int *ptr) { +EXPORT void increment_int(int32_t *ptr) { *ptr += 1; } /* Test: test_init_int */ -EXPORT void init_int(int *ptr, int val) { +EXPORT void init_int(int32_t *ptr, int32_t val) { *ptr = val; } /* Test: test_init_array */ -EXPORT void init_array(int *array, size_t len, int val) { +EXPORT void init_array(int32_t *array, size_t len, int32_t val) { for (size_t i = 0; i < len; i++) { array[i] = val; } @@ -26,28 +27,28 @@ EXPORT void init_array(int *array, size_t len, int val) { /* Test: test_init_static_inner */ typedef struct SyncPtr { - int *ptr; + int32_t *ptr; } SyncPtr; -EXPORT void init_static_inner(const SyncPtr *s_ptr, int val) { +EXPORT void init_static_inner(const SyncPtr *s_ptr, int32_t val) { *(s_ptr->ptr) = val; } /* Tests: test_exposed, test_pass_dangling */ -EXPORT void ignore_ptr(__attribute__((unused)) const int *ptr) { +EXPORT void ignore_ptr(__attribute__((unused)) const int32_t *ptr) { return; } /* Test: test_expose_int */ -EXPORT void expose_int(const int *int_ptr, const int **pptr) { +EXPORT void expose_int(const int32_t *int_ptr, const int32_t **pptr) { *pptr = int_ptr; } /* Test: test_swap_ptr */ -EXPORT void swap_ptr(const int **pptr0, const int **pptr1) { - const int *tmp = *pptr0; +EXPORT void swap_ptr(const int32_t **pptr0, const int32_t **pptr1) { + const int32_t *tmp = *pptr0; *pptr0 = *pptr1; *pptr1 = tmp; } @@ -55,36 +56,54 @@ EXPORT void swap_ptr(const int **pptr0, const int **pptr1) { /* Test: test_swap_ptr_tuple */ typedef struct Tuple { - int *ptr0; - int *ptr1; + int32_t *ptr0; + int32_t *ptr1; } Tuple; EXPORT void swap_ptr_tuple(Tuple *t_ptr) { - int *tmp = t_ptr->ptr0; + int32_t *tmp = t_ptr->ptr0; t_ptr->ptr0 = t_ptr->ptr1; t_ptr->ptr1 = tmp; } /* Test: test_overwrite_dangling */ -EXPORT void overwrite_ptr(const int **pptr) { +EXPORT void overwrite_ptr(const int32_t **pptr) { *pptr = NULL; } /* Test: test_swap_ptr_triple_dangling */ typedef struct Triple { - int *ptr0; - int *ptr1; - int *ptr2; + int32_t *ptr0; + int32_t *ptr1; + int32_t *ptr2; } Triple; EXPORT void swap_ptr_triple_dangling(Triple *t_ptr) { - int *tmp = t_ptr->ptr0; + int32_t *tmp = t_ptr->ptr0; t_ptr->ptr0 = t_ptr->ptr2; t_ptr->ptr2 = tmp; } -EXPORT const int *return_ptr(const int *ptr) { +EXPORT const int32_t *return_ptr(const int32_t *ptr) { return ptr; } + +/* Test: test_pass_ptr_as_int */ + +EXPORT void pass_ptr_as_int(uintptr_t ptr, int32_t set_to_val) { + *(int32_t*)ptr = set_to_val; +} + +/* Test: test_pass_ptr_via_previously_shared_mem */ + +int32_t** shared_place; + +EXPORT void set_shared_mem(int32_t** ptr) { + shared_place = ptr; +} + +EXPORT void init_ptr_stored_in_shared_mem(int32_t val) { + **shared_place = val; +} diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c index 6da730a498724..acccf06f3df2b 100644 --- a/src/tools/miri/tests/native-lib/scalar_arguments.c +++ b/src/tools/miri/tests/native-lib/scalar_arguments.c @@ -1,9 +1,10 @@ #include +#include // See comments in build_native_lib() #define EXPORT __attribute__((visibility("default"))) -EXPORT int add_one_int(int x) { +EXPORT int32_t add_one_int(int32_t x) { return 2 + x; } @@ -13,23 +14,23 @@ EXPORT void printer(void) { // function with many arguments, to test functionality when some args are stored // on the stack -EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { +EXPORT int32_t test_stack_spill(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f, int32_t g, int32_t h, int32_t i, int32_t j, int32_t k, int32_t l) { return a+b+c+d+e+f+g+h+i+j+k+l; } -EXPORT unsigned int get_unsigned_int(void) { +EXPORT uint32_t get_unsigned_int(void) { return -10; } -EXPORT short add_int16(short x) { +EXPORT short add_int16(int16_t x) { return x + 3; } -EXPORT long add_short_to_long(short x, long y) { +EXPORT long add_short_to_long(int16_t x, int64_t y) { return x + y; } // To test that functions not marked with EXPORT cannot be called by Miri. -int not_exported(void) { +int32_t not_exported(void) { return 0; } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 457d0afe3b5b7..3fb3284e3d7fd 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2359,6 +2359,21 @@ impl Rewrite for ast::Param { } } +fn rewrite_opt_lifetime( + context: &RewriteContext<'_>, + lifetime: Option, +) -> RewriteResult { + let Some(l) = lifetime else { + return Ok(String::new()); + }; + let mut result = l.rewrite_result( + context, + Shape::legacy(context.config.max_width(), Indent::empty()), + )?; + result.push(' '); + Ok(result) +} + fn rewrite_explicit_self( context: &RewriteContext<'_>, explicit_self: &ast::ExplicitSelf, @@ -2367,58 +2382,34 @@ fn rewrite_explicit_self( shape: Shape, has_multiple_attr_lines: bool, ) -> RewriteResult { - match explicit_self.node { + let self_str = match explicit_self.node { ast::SelfKind::Region(lt, m) => { let mut_str = format_mutability(m); - match lt { - Some(ref l) => { - let lifetime_str = l.rewrite_result( - context, - Shape::legacy(context.config.max_width(), Indent::empty()), - )?; - Ok(combine_strs_with_missing_comments( - context, - param_attrs, - &format!("&{lifetime_str} {mut_str}self"), - span, - shape, - !has_multiple_attr_lines, - )?) - } - None => Ok(combine_strs_with_missing_comments( - context, - param_attrs, - &format!("&{mut_str}self"), - span, - shape, - !has_multiple_attr_lines, - )?), - } + let lifetime_str = rewrite_opt_lifetime(context, lt)?; + format!("&{lifetime_str}{mut_str}self") + } + ast::SelfKind::Pinned(lt, m) => { + let mut_str = m.ptr_str(); + let lifetime_str = rewrite_opt_lifetime(context, lt)?; + format!("&{lifetime_str}pin {mut_str} self") } ast::SelfKind::Explicit(ref ty, mutability) => { let type_str = ty.rewrite_result( context, Shape::legacy(context.config.max_width(), Indent::empty()), )?; - - Ok(combine_strs_with_missing_comments( - context, - param_attrs, - &format!("{}self: {}", format_mutability(mutability), type_str), - span, - shape, - !has_multiple_attr_lines, - )?) + format!("{}self: {}", format_mutability(mutability), type_str) } - ast::SelfKind::Value(mutability) => Ok(combine_strs_with_missing_comments( - context, - param_attrs, - &format!("{}self", format_mutability(mutability)), - span, - shape, - !has_multiple_attr_lines, - )?), - } + ast::SelfKind::Value(mutability) => format!("{}self", format_mutability(mutability)), + }; + Ok(combine_strs_with_missing_comments( + context, + param_attrs, + &self_str, + span, + shape, + !has_multiple_attr_lines, + )?) } pub(crate) fn span_lo_for_param(param: &ast::Param) -> BytePos { diff --git a/src/tools/rustfmt/tests/source/pin_sugar.rs b/src/tools/rustfmt/tests/source/pin_sugar.rs index 0eb3c0770c482..370dfbc196aea 100644 --- a/src/tools/rustfmt/tests/source/pin_sugar.rs +++ b/src/tools/rustfmt/tests/source/pin_sugar.rs @@ -8,3 +8,13 @@ fn g<'a>(x: & 'a pin const i32) {} fn h<'a>(x: & 'a pin mut i32) {} fn i(x: &pin mut i32) {} + +struct Foo; + +impl Foo { + fn f(&pin const self) {} + fn g<'a>(& 'a pin const self) {} + fn h<'a>(& 'a pin +mut self) {} + fn i(&pin mut self) {} +} diff --git a/src/tools/rustfmt/tests/target/pin_sugar.rs b/src/tools/rustfmt/tests/target/pin_sugar.rs index c9fa883e238fd..7d04efb1b3266 100644 --- a/src/tools/rustfmt/tests/target/pin_sugar.rs +++ b/src/tools/rustfmt/tests/target/pin_sugar.rs @@ -7,3 +7,12 @@ fn f(x: &pin const i32) {} fn g<'a>(x: &'a pin const i32) {} fn h<'a>(x: &'a pin mut i32) {} fn i(x: &pin mut i32) {} + +struct Foo; + +impl Foo { + fn f(&pin const self) {} + fn g<'a>(&'a pin const self) {} + fn h<'a>(&'a pin mut self) {} + fn i(&pin mut self) {} +} diff --git a/tests/codegen/pattern_type_symbols.rs b/tests/codegen/pattern_type_symbols.rs index b504a3508f94c..e86a9ef27de1b 100644 --- a/tests/codegen/pattern_type_symbols.rs +++ b/tests/codegen/pattern_type_symbols.rs @@ -16,7 +16,7 @@ pub fn bar() { // CHECK: call pattern_type_symbols::foo:: // CHECK: call void @_RINvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_20pattern_type_symbols3foomEB2_ foo::(); - // CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999], [(); true])> - // CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_ + // CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999])> + // CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_EEB2_ foo::(); } diff --git a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir index 5ff90de961506..cc01f51973c84 100644 --- a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir +++ b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir @@ -3,9 +3,9 @@ fn main() -> () { let mut _0: (); scope 1 { - debug x => const 2_u32 is 1..=; + debug x => const 2_u32 is 1..; scope 2 { - debug y => const {transmute(0x00000000): (u32) is 1..=}; + debug y => const {transmute(0x00000000): (u32) is 1..}; } } diff --git a/tests/mir-opt/pattern_types.rs b/tests/mir-opt/pattern_types.rs index 0369ccf9a9d56..d5847b95f7328 100644 --- a/tests/mir-opt/pattern_types.rs +++ b/tests/mir-opt/pattern_types.rs @@ -5,8 +5,8 @@ use std::pat::pattern_type; // EMIT_MIR pattern_types.main.PreCodegen.after.mir fn main() { - // CHECK: debug x => const 2_u32 is 1..= + // CHECK: debug x => const 2_u32 is 1.. let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(2) }; - // CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=} + // CHECK: debug y => const {transmute(0x00000000): (u32) is 1..} let y: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; } diff --git a/tests/pretty/pin-ergonomics.rs b/tests/pretty/pin-ergonomics.rs new file mode 100644 index 0000000000000..47ffc97b1183f --- /dev/null +++ b/tests/pretty/pin-ergonomics.rs @@ -0,0 +1,24 @@ +//@ pp-exact + +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +struct Foo; + +impl Foo { + fn baz(&pin mut self) {} + + fn baz_const(&pin const self) {} + + fn baz_lt<'a>(&'a pin mut self) {} + + fn baz_const_lt(&'_ pin const self) {} +} + +fn foo(_: &pin mut Foo) {} +fn foo_lt<'a>(_: &'a pin mut Foo) {} + +fn foo_const(_: &pin const Foo) {} +fn foo_const_lt(_: &'_ pin const Foo) {} + +fn main() {} diff --git a/tests/run-make/repr128-dwarf/main.rs b/tests/run-make/repr128-dwarf/main.rs index 57923a8386db9..9842ab4a3426f 100644 --- a/tests/run-make/repr128-dwarf/main.rs +++ b/tests/run-make/repr128-dwarf/main.rs @@ -19,8 +19,33 @@ pub enum I128Enum { I128D = i128::MAX.to_le(), } +#[cfg(not(old_llvm))] +#[repr(u128)] +pub enum U128VariantEnum { + VariantU128A(u8) = 0_u128.to_le(), + VariantU128B = 1_u128.to_le(), + VariantU128C = (u64::MAX as u128 + 1).to_le(), + VariantU128D = u128::MAX.to_le(), +} + +#[cfg(not(old_llvm))] +#[repr(i128)] +pub enum I128VariantEnum { + VariantI128A(u8) = 0_i128.to_le(), + VariantI128B = (-1_i128).to_le(), + VariantI128C = i128::MIN.to_le(), + VariantI128D = i128::MAX.to_le(), +} + pub fn f(_: U128Enum, _: I128Enum) {} +#[cfg(not(old_llvm))] +pub fn g(_: U128VariantEnum, _: I128VariantEnum) {} + fn main() { f(U128Enum::U128A, I128Enum::I128A); + #[cfg(not(old_llvm))] + { + g(U128VariantEnum::VariantU128A(1), I128VariantEnum::VariantI128A(2)); + } } diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs index 2fd54c186b934..15eb186717f6d 100644 --- a/tests/run-make/repr128-dwarf/rmake.rs +++ b/tests/run-make/repr128-dwarf/rmake.rs @@ -5,13 +5,32 @@ use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; +use gimli::read::DebuggingInformationEntry; use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian}; use object::{Object, ObjectSection}; use run_make_support::{gimli, object, rfs, rustc}; fn main() { + // Before LLVM 20, 128-bit enums with variants didn't emit debuginfo correctly. + // This check can be removed once Rust no longer supports LLVM 18 and 19. + let llvm_version = rustc() + .verbose() + .arg("--version") + .run() + .stdout_utf8() + .lines() + .filter_map(|line| line.strip_prefix("LLVM version: ")) + .map(|version| version.split(".").next().unwrap().parse::().unwrap()) + .next() + .unwrap(); + let is_old_llvm = llvm_version < 20; + let output = PathBuf::from("repr128"); - rustc().input("main.rs").output(&output).arg("-Cdebuginfo=2").run(); + let mut rustc = rustc(); + if is_old_llvm { + rustc.cfg("old_llvm"); + } + rustc.input("main.rs").output(&output).arg("-Cdebuginfo=2").run(); // Mach-O uses packed debug info let dsym_location = output .with_extension("dSYM") @@ -29,7 +48,8 @@ fn main() { }) .unwrap(); let mut iter = dwarf.units(); - let mut still_to_find = HashMap::from([ + + let mut enumerators_to_find = HashMap::from([ ("U128A", 0_u128), ("U128B", 1_u128), ("U128C", u64::MAX as u128 + 1), @@ -39,35 +59,88 @@ fn main() { ("I128C", i128::MIN as u128), ("I128D", i128::MAX as u128), ]); + let mut variants_to_find = HashMap::from([ + ("VariantU128A", 0_u128), + ("VariantU128B", 1_u128), + ("VariantU128C", u64::MAX as u128 + 1), + ("VariantU128D", u128::MAX), + ("VariantI128A", 0_i128 as u128), + ("VariantI128B", (-1_i128) as u128), + ("VariantI128C", i128::MIN as u128), + ("VariantI128D", i128::MAX as u128), + ]); + while let Some(header) = iter.next().unwrap() { let unit = dwarf.unit(header).unwrap(); let mut cursor = unit.entries(); + + let get_name = |entry: &DebuggingInformationEntry<'_, '_, _>| { + let name = dwarf + .attr_string( + &unit, + entry.attr(gimli::constants::DW_AT_name).unwrap().unwrap().value(), + ) + .unwrap(); + name.to_string().unwrap().to_string() + }; + while let Some((_, entry)) = cursor.next_dfs().unwrap() { - if entry.tag() == gimli::constants::DW_TAG_enumerator { - let name = dwarf - .attr_string( - &unit, - entry.attr(gimli::constants::DW_AT_name).unwrap().unwrap().value(), - ) - .unwrap(); - let name = name.to_string().unwrap(); - if let Some(expected) = still_to_find.remove(name.as_ref()) { - match entry.attr(gimli::constants::DW_AT_const_value).unwrap().unwrap().value() + match entry.tag() { + gimli::constants::DW_TAG_variant if !is_old_llvm => { + let value = match entry + .attr(gimli::constants::DW_AT_discr_value) + .unwrap() + .unwrap() + .value() { - AttributeValue::Block(value) => { - assert_eq!( - value.to_slice().unwrap(), - expected.to_le_bytes().as_slice(), - "{name}" - ); + AttributeValue::Block(value) => value.to_slice().unwrap().to_vec(), + value => panic!("unexpected DW_AT_discr_value of {value:?}"), + }; + // The `DW_TAG_member` that is a child of `DW_TAG_variant` will contain the + // variant's name. + let Some((1, child_entry)) = cursor.next_dfs().unwrap() else { + panic!("Missing child of DW_TAG_variant"); + }; + assert_eq!(child_entry.tag(), gimli::constants::DW_TAG_member); + let name = get_name(child_entry); + if let Some(expected) = variants_to_find.remove(name.as_str()) { + // This test uses LE byte order is used for consistent values across + // architectures. + assert_eq!(value.as_slice(), expected.to_le_bytes().as_slice(), "{name}"); + } + } + + gimli::constants::DW_TAG_enumerator => { + let name = get_name(entry); + if let Some(expected) = enumerators_to_find.remove(name.as_str()) { + match entry + .attr(gimli::constants::DW_AT_const_value) + .unwrap() + .unwrap() + .value() + { + AttributeValue::Block(value) => { + // This test uses LE byte order is used for consistent values across + // architectures. + assert_eq!( + value.to_slice().unwrap(), + expected.to_le_bytes().as_slice(), + "{name}" + ); + } + value => panic!("{name}: unexpected DW_AT_const_value of {value:?}"), } - value => panic!("{name}: unexpected DW_AT_const_value of {value:?}"), } } + + _ => {} } } } - if !still_to_find.is_empty() { - panic!("Didn't find debug entries for {still_to_find:?}"); + if !enumerators_to_find.is_empty() { + panic!("Didn't find debug enumerator entries for {enumerators_to_find:?}"); + } + if !is_old_llvm && !variants_to_find.is_empty() { + panic!("Didn't find debug variant entries for {variants_to_find:?}"); } } diff --git a/tests/rustdoc/doc-hidden-reexports-109449.rs b/tests/rustdoc/doc-hidden-reexports-109449.rs index 8f195544120af..78b9214300a95 100644 --- a/tests/rustdoc/doc-hidden-reexports-109449.rs +++ b/tests/rustdoc/doc-hidden-reexports-109449.rs @@ -26,21 +26,21 @@ pub mod single_reexport { //@ has 'foo/single_reexport/index.html' // First we check that we have 4 type aliases. - //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 4 + //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 0 // Then we check that we have the correct link for each re-export. //@ !has - '//*[@href="struct.Foo.html"]' 'Foo' - //@ has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;' + //@ !has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;' pub use crate::private_module::Public as Foo; //@ !has - '//*[@href="type.Foo2.html"]' 'Foo2' - //@ has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;' + //@ !has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;' pub use crate::private_module::Bar as Foo2; //@ !has - '//*[@href="type.Yo.html"]' 'Yo' - //@ has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;' + //@ !has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;' pub use crate::Bar3 as Yo; //@ !has - '//*[@href="struct.Yo2.html"]' 'Yo2' - //@ has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;' + //@ !has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;' pub use crate::FooFoo as Yo2; // Checking that each file is also created as expected. @@ -70,19 +70,19 @@ pub mod single_reexport_no_inline { //@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Re-exports' // Now we check that we don't have links to the items, just `pub use`. - //@ has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;' + //@ !has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;' //@ !has - '//*[@id="main-content"]//a' 'XFoo' #[doc(no_inline)] pub use crate::private_module::Public as XFoo; - //@ has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;' + //@ !has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;' //@ !has - '//*[@id="main-content"]//a' 'Foo2' #[doc(no_inline)] pub use crate::private_module::Bar as Foo2; - //@ has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;' + //@ !has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;' //@ !has - '//*[@id="main-content"]//a' 'Yo' #[doc(no_inline)] pub use crate::Bar3 as Yo; - //@ has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;' + //@ !has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;' //@ !has - '//*[@id="main-content"]//a' 'Yo2' #[doc(no_inline)] pub use crate::FooFoo as Yo2; diff --git a/tests/rustdoc/doc-hidden-source.rs b/tests/rustdoc/doc-hidden-source.rs new file mode 100644 index 0000000000000..b6bc622dd584f --- /dev/null +++ b/tests/rustdoc/doc-hidden-source.rs @@ -0,0 +1,16 @@ +// Test for . + +#![crate_name = "foo"] + +//@ has 'foo/index.html' +//@ !has - '//*[@id="main-content"]//*[@class="struct"]' 'Bar' +#[doc(hidden)] +pub struct Bar; + +//@ !has - '//*' 'pub use crate::Bar as A;' +pub use crate::Bar as A; +//@ !has - '//*' 'pub use crate::A as B;' +pub use crate::A as B; +//@ has - '//dt/a[@class="struct"]' 'C' +#[doc(inline)] +pub use crate::Bar as C; diff --git a/tests/rustdoc/impl-parts-crosscrate.rs b/tests/rustdoc/impl-parts-crosscrate.rs index 49752ab75d512..631c8bb3eb318 100644 --- a/tests/rustdoc/impl-parts-crosscrate.rs +++ b/tests/rustdoc/impl-parts-crosscrate.rs @@ -5,7 +5,7 @@ extern crate rustdoc_impl_parts_crosscrate; -pub struct Bar { t: T } +pub struct Bar { t: T } // The output file is html embedded in javascript, so the html tags // aren't stripped by the processing script and we can't check for the diff --git a/tests/rustdoc/impl-parts.rs b/tests/rustdoc/impl-parts.rs index 820f51008a40c..4f281bfd63c83 100644 --- a/tests/rustdoc/impl-parts.rs +++ b/tests/rustdoc/impl-parts.rs @@ -3,7 +3,7 @@ pub auto trait AnAutoTrait {} -pub struct Foo { field: T } +pub struct Foo { field: T } //@ has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \ // "impl !AnAutoTrait for Foowhere T: Sync + Clone," diff --git a/tests/rustdoc/inline_cross/inline_hidden.rs b/tests/rustdoc/inline_cross/inline_hidden.rs index 49ca2db6a2245..f6727de2cc67f 100644 --- a/tests/rustdoc/inline_cross/inline_hidden.rs +++ b/tests/rustdoc/inline_cross/inline_hidden.rs @@ -6,7 +6,7 @@ extern crate rustdoc_hidden; //@ has inline_hidden/index.html // Ensures this item is not inlined. -//@ has - '//*[@id="reexport.Foo"]/code' 'pub use rustdoc_hidden::Foo;' +//@ !has - '//*[@id="reexport.Foo"]/code' 'pub use rustdoc_hidden::Foo;' #[doc(no_inline)] pub use rustdoc_hidden::Foo; @@ -16,7 +16,7 @@ pub use rustdoc_hidden::Foo; pub use rustdoc_hidden::Foo as Inlined; // Even with this import, we should not see `Foo`. -//@ count - '//dt' 4 +//@ count - '//dt' 3 //@ has - '//dt/a[@class="struct"]' 'Bar' //@ has - '//dt/a[@class="fn"]' 'foo' pub use rustdoc_hidden::*; diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs index e4a406c3845ad..aef302eb0b29a 100644 --- a/tests/rustdoc/reexport-attr-merge.rs +++ b/tests/rustdoc/reexport-attr-merge.rs @@ -18,7 +18,7 @@ pub use Foo1 as Foo2; // First we ensure that only the reexport `Bar2` and the inlined struct `Bar` // are inlined. -//@ count - '//a[@class="struct"]' 2 +//@ count - '//a[@class="struct"]' 1 // Then we check that `cfg` is displayed for base item, but not for intermediate re-exports. //@ has - '//*[@class="stab portability"]' 'foo' //@ !has - '//*[@class="stab portability"]' 'bar' @@ -29,5 +29,5 @@ pub use Foo2 as Bar; // This one should appear but `Bar2` won't be linked because there is no // `#[doc(inline)]`. -//@ has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;' +//@ !has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;' pub use Foo2 as Bar2; diff --git a/tests/rustdoc/reexport-doc-hidden-inside-private.rs b/tests/rustdoc/reexport-doc-hidden-inside-private.rs index 8e194ef74fb82..bae2aa78ec7a3 100644 --- a/tests/rustdoc/reexport-doc-hidden-inside-private.rs +++ b/tests/rustdoc/reexport-doc-hidden-inside-private.rs @@ -9,8 +9,8 @@ mod private_module { } //@ has 'foo/index.html' -//@ has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;' +//@ !has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;' pub use crate::private_module::Public as Foo; // Glob re-exports with no visible items should not be displayed. -//@ count - '//*[@class="item-table reexports"]/dt' 1 +//@ count - '//*[@class="item-table reexports"]/dt' 0 pub use crate::private_module::*; diff --git a/tests/rustdoc/reexport-doc-hidden.rs b/tests/rustdoc/reexport-doc-hidden.rs index b912362f2987a..1468e9ad957f7 100644 --- a/tests/rustdoc/reexport-doc-hidden.rs +++ b/tests/rustdoc/reexport-doc-hidden.rs @@ -8,7 +8,7 @@ pub type Type = u32; //@ has 'foo/index.html' -//@ has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;' +//@ !has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;' pub use crate::Type as Type2; //@ count - '//*[@id="reexport.Type3"]' 0 @@ -21,5 +21,5 @@ macro_rules! foo { () => {}; } -//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' +//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' pub use crate::foo as Macro; diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport-hidden-macro.rs index 9b83bca3906d2..7345149c64522 100644 --- a/tests/rustdoc/reexport-hidden-macro.rs +++ b/tests/rustdoc/reexport-hidden-macro.rs @@ -5,7 +5,7 @@ //@ has 'foo/index.html' //@ has - '//*[@id="main-content"]//a[@href="macro.Macro2.html"]' 'Macro2' -//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' +//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' //@ has 'foo/macro.Macro2.html' //@ has - '//*[@class="docblock"]' 'Displayed' diff --git a/tests/rustdoc/reexport-of-doc-hidden.rs b/tests/rustdoc/reexport-of-doc-hidden.rs index 21511bc2aea99..e901d0ff8a2bc 100644 --- a/tests/rustdoc/reexport-of-doc-hidden.rs +++ b/tests/rustdoc/reexport-of-doc-hidden.rs @@ -12,13 +12,13 @@ macro_rules! foo { } //@ has 'foo/index.html' -//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' +//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' pub use crate::foo as Macro; -//@ has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;' +//@ !has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;' pub use crate::foo as Macro2; -//@ has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;' +//@ !has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;' pub use crate::Bar as Boo; -//@ has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;' +//@ !has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;' pub use crate::Bar as Boo2; pub fn fofo() {} @@ -30,9 +30,9 @@ pub use crate::fofo as f2; pub mod sub { //@ has 'foo/sub/index.html' - //@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' + //@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;' pub use crate::foo as Macro; - //@ has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;' + //@ !has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;' pub use crate::foo as Macro2; //@ has - '//*[@id="reexport.f1"]/code' 'pub use crate::fofo as f1;' diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 57cc48aa9cf47..48fa2bf29bc40 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -38,7 +38,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 6738017673003..bfdf94c99007c 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -49,7 +49,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 6738017673003..bfdf94c99007c 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -49,7 +49,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 6738017673003..bfdf94c99007c 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -49,7 +49,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 57cc48aa9cf47..48fa2bf29bc40 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -38,7 +38,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 6738017673003..bfdf94c99007c 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -49,7 +49,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index 5f73ff7d6bd58..2239ba0e5880a 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(test) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -48,7 +48,7 @@ error: fn_abi_of(test) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -107,7 +107,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -155,7 +155,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -205,7 +205,7 @@ error: fn_abi_of(test_generic) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Pointer( AddressSpace( @@ -245,7 +245,7 @@ error: fn_abi_of(test_generic) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -292,7 +292,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -331,7 +331,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -366,7 +366,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -405,7 +405,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -446,7 +446,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Array { @@ -486,7 +486,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -521,7 +521,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Array { @@ -561,7 +561,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -602,7 +602,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Float( F32, @@ -640,7 +640,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -675,7 +675,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -714,7 +714,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -755,7 +755,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -794,7 +794,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -829,7 +829,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -868,7 +868,7 @@ error: ABIs are not compatible abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -923,7 +923,7 @@ error: fn_abi_of(assoc_test) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Pointer( AddressSpace( @@ -975,7 +975,7 @@ error: fn_abi_of(assoc_test) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index ec85030c10686..59d7b00441790 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -38,7 +38,7 @@ error: fn_abi_of(pass_zst) = FnAbi { abi: $SOME_ALIGN, pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.fixed b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.fixed new file mode 100644 index 0000000000000..7af986267aa67 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.fixed @@ -0,0 +1,40 @@ +//@ edition: 2021 +//@ run-rustfix +#![feature(return_type_notation)] +#![allow(dead_code)] + +trait Trait { + async fn method() {} +} + +fn foo>() {} +//~^ ERROR argument types not allowed with return type notation + +fn bar>() {} +//~^ ERROR return type not allowed with return type notation + +fn baz>() {} +//~^ ERROR return type notation arguments must be elided with `..` + +fn foo_path() where T::method(..): Send {} +//~^ ERROR argument types not allowed with return type notation + +fn bar_path() where T::method(..): Send {} +//~^ ERROR return type not allowed with return type notation + +fn bay_path() where T::method(..): Send {} +//~^ ERROR return type not allowed with return type notation + +fn baz_path() where T::method(..): Send {} +//~^ ERROR return type notation arguments must be elided with `..` + +fn foo_qualified() where T::method(..): Send {} +//~^ ERROR expected associated type + +fn bar_qualified() where T::method(..): Send {} +//~^ ERROR expected associated type + +fn baz_qualified() where T::method(..): Send {} +//~^ ERROR expected associated type + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index 90fd2c2b4f326..983836e6433f0 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -1,6 +1,7 @@ //@ edition: 2021 - +//@ run-rustfix #![feature(return_type_notation)] +#![allow(dead_code)] trait Trait { async fn method() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr index bd02b7d6534a9..e1245a04c7f7d 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr @@ -1,5 +1,5 @@ error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:24:45 + --> $DIR/bad-inputs-and-output.rs:25:45 | LL | fn bay_path() where T::method(..) -> (): Send {} | ^^^^^ @@ -11,25 +11,43 @@ LL + fn bay_path() where T::method(..): Send {} | error[E0575]: expected associated type, found associated function `Trait::method` - --> $DIR/bad-inputs-and-output.rs:30:36 + --> $DIR/bad-inputs-and-output.rs:31:36 | LL | fn foo_qualified() where ::method(i32): Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type + | +help: you might have meant to use the return type notation syntax + | +LL - fn foo_qualified() where ::method(i32): Send {} +LL + fn foo_qualified() where T::method(..): Send {} + | error[E0575]: expected associated type, found associated function `Trait::method` - --> $DIR/bad-inputs-and-output.rs:33:36 + --> $DIR/bad-inputs-and-output.rs:34:36 | LL | fn bar_qualified() where ::method() -> (): Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type + | +help: you might have meant to use the return type notation syntax + | +LL - fn bar_qualified() where ::method() -> (): Send {} +LL + fn bar_qualified() where T::method(..): Send {} + | error[E0575]: expected associated type, found associated function `Trait::method` - --> $DIR/bad-inputs-and-output.rs:36:36 + --> $DIR/bad-inputs-and-output.rs:37:36 | LL | fn baz_qualified() where ::method(): Send {} | ^^^^^^^^^^^^^^^^^^^^^^ not a associated type + | +help: you might have meant to use the return type notation syntax + | +LL - fn baz_qualified() where ::method(): Send {} +LL + fn baz_qualified() where T::method(..): Send {} + | error: argument types not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:9:23 + --> $DIR/bad-inputs-and-output.rs:10:23 | LL | fn foo>() {} | ^^^^^ @@ -41,7 +59,7 @@ LL + fn foo>() {} | error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:12:25 + --> $DIR/bad-inputs-and-output.rs:13:25 | LL | fn bar (): Send>>() {} | ^^^^^^ @@ -53,7 +71,7 @@ LL + fn bar>() {} | error: return type notation arguments must be elided with `..` - --> $DIR/bad-inputs-and-output.rs:15:23 + --> $DIR/bad-inputs-and-output.rs:16:23 | LL | fn baz>() {} | ^^ @@ -64,7 +82,7 @@ LL | fn baz>() {} | ++ error: argument types not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:18:40 + --> $DIR/bad-inputs-and-output.rs:19:40 | LL | fn foo_path() where T::method(i32): Send {} | ^^^^^ @@ -76,7 +94,7 @@ LL + fn foo_path() where T::method(..): Send {} | error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:21:42 + --> $DIR/bad-inputs-and-output.rs:22:42 | LL | fn bar_path() where T::method() -> (): Send {} | ^^^^^^ @@ -88,7 +106,7 @@ LL + fn bar_path() where T::method(..): Send {} | error: return type notation arguments must be elided with `..` - --> $DIR/bad-inputs-and-output.rs:27:40 + --> $DIR/bad-inputs-and-output.rs:28:40 | LL | fn baz_path() where T::method(): Send {} | ^^ diff --git a/tests/ui/associated-types/ident-from-macro-expansion.rs b/tests/ui/associated-types/ident-from-macro-expansion.rs new file mode 100644 index 0000000000000..6aabe4571406c --- /dev/null +++ b/tests/ui/associated-types/ident-from-macro-expansion.rs @@ -0,0 +1,23 @@ +trait Trait {} +impl Trait for () {} + +macro_rules! fully_qualified { + ($id:ident) => { + <() as Trait>::$id + } +} + +macro_rules! type_dependent { + ($t:ident, $id:ident) => { + T::$id + } +} + +fn t() { + let x: fully_qualified!(Assoc); + //~^ ERROR cannot find associated type `Assoc` in trait `Trait` + let x: type_dependent!(T, Assoc); + //~^ ERROR associated type `Assoc` not found for `T` +} + +fn main() {} diff --git a/tests/ui/associated-types/ident-from-macro-expansion.stderr b/tests/ui/associated-types/ident-from-macro-expansion.stderr new file mode 100644 index 0000000000000..dabf13c2c1726 --- /dev/null +++ b/tests/ui/associated-types/ident-from-macro-expansion.stderr @@ -0,0 +1,22 @@ +error[E0576]: cannot find associated type `Assoc` in trait `Trait` + --> $DIR/ident-from-macro-expansion.rs:17:29 + | +LL | <() as Trait>::$id + | --- due to this macro variable +... +LL | let x: fully_qualified!(Assoc); + | ^^^^^ not found in `Trait` + +error[E0220]: associated type `Assoc` not found for `T` + --> $DIR/ident-from-macro-expansion.rs:19:31 + | +LL | T::$id + | --- due to this macro variable +... +LL | let x: type_dependent!(T, Assoc); + | ^^^^^ associated type `Assoc` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0220, E0576. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/async-await/async-closures/kind-due-to-rpit.rs b/tests/ui/async-await/async-closures/kind-due-to-rpit.rs new file mode 100644 index 0000000000000..ad19d93b93a3c --- /dev/null +++ b/tests/ui/async-await/async-closures/kind-due-to-rpit.rs @@ -0,0 +1,14 @@ +//@ edition: 2024 + +// Make sure the error message is understandable when an `AsyncFn` goal is not satisfied +// (due to closure kind), and that goal originates from an RPIT. + +fn repro(foo: impl Into) -> impl AsyncFn() { + let inner_fn = async move || { + //~^ ERROR expected a closure that implements the `AsyncFn` trait + let _ = foo.into(); + }; + inner_fn +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/kind-due-to-rpit.stderr b/tests/ui/async-await/async-closures/kind-due-to-rpit.stderr new file mode 100644 index 0000000000000..982cc50e14f97 --- /dev/null +++ b/tests/ui/async-await/async-closures/kind-due-to-rpit.stderr @@ -0,0 +1,17 @@ +error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce` + --> $DIR/kind-due-to-rpit.rs:7:20 + | +LL | fn repro(foo: impl Into) -> impl AsyncFn() { + | -------------- the requirement to implement `AsyncFn` derives from here +LL | let inner_fn = async move || { + | ^^^^^^^^^^^^^ this closure implements `AsyncFnOnce`, not `AsyncFn` +LL | +LL | let _ = foo.into(); + | --- closure is `AsyncFnOnce` because it moves the variable `foo` out of its environment +LL | }; +LL | inner_fn + | -------- return type was inferred to be `{async closure@$DIR/kind-due-to-rpit.rs:7:20: 7:33}` here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/async-await/pin-ergonomics/sugar-self.rs b/tests/ui/async-await/pin-ergonomics/sugar-self.rs new file mode 100644 index 0000000000000..3d71b54b1aec3 --- /dev/null +++ b/tests/ui/async-await/pin-ergonomics/sugar-self.rs @@ -0,0 +1,46 @@ +//@ check-pass + +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +// Makes sure we can handle `&pin mut self` and `&pin const self` as sugar for +// `self: Pin<&mut Self>` and `self: Pin<&Self>`. + +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn baz(&pin mut self) {} + + fn baz_const(&pin const self) {} + + fn baz_lt<'a>(&'a pin mut self) {} + + fn baz_const_lt(&'_ pin const self) {} +} + +fn foo(_: &pin mut Foo) {} + +fn foo_const(_: &pin const Foo) {} + +fn bar(x: &pin mut Foo) { + // For the calls below to work we need to automatically reborrow, + // as if the user had written `foo(x.as_mut())`. + foo(x); + foo(x); + + Foo::baz(x); + Foo::baz(x); + + // make sure we can reborrow &mut as &. + foo_const(x); + Foo::baz_const(x); + + let x: &pin const _ = Pin::new(&Foo); + + foo_const(x); // make sure reborrowing from & to & works. + foo_const(x); +} + +fn main() {} diff --git a/tests/ui/attributes/decl_macro_ty_in_attr_macro.rs b/tests/ui/attributes/decl_macro_ty_in_attr_macro.rs new file mode 100644 index 0000000000000..e633c08be3ad2 --- /dev/null +++ b/tests/ui/attributes/decl_macro_ty_in_attr_macro.rs @@ -0,0 +1,20 @@ +// tests for #137662: using a ty or (or most other) fragment inside an attr macro wouldn't work +// because of a missing code path. With $repr: tt it did work. +//@ check-pass + +macro_rules! foo { + { + $repr:ty + } => { + #[repr($repr)] + pub enum Foo { + Bar = 0i32, + } + } +} + +foo! { + i32 +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs index 24b878927530c..15ca0577e4acb 100644 --- a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs +++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs @@ -8,10 +8,14 @@ struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR found both positive and negative implementation +impl !Send for TestType {} +//~^ ERROR found both positive and negative implementation +//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not -unsafe impl Send for TestType {} //~ ERROR conflicting implementations +unsafe impl Send for TestType {} +//~^ ERROR conflicting implementations impl !Send for TestType {} +//~^ ERROR `!Send` impls cannot be specialized fn main() {} diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr index 2463f38a92251..c6aed150201d8 100644 --- a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr +++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -8,7 +8,7 @@ LL | impl !Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>` - --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1 + --> $DIR/coherence-conflicting-negative-trait-impl.rs:15:1 | LL | unsafe impl Send for TestType {} | ------------------------------------------------------ first implementation here @@ -16,7 +16,32 @@ LL | unsafe impl Send for TestType {} LL | unsafe impl Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` -error: aborting due to 2 previous errors +error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not + --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:9 + | +LL | impl !Send for TestType {} + | ^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1 + | +LL | struct TestType(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^ + +error[E0366]: `!Send` impls cannot be specialized + --> $DIR/coherence-conflicting-negative-trait-impl.rs:18:1 + | +LL | impl !Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `i32` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1 + | +LL | struct TestType(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0119, E0751. +Some errors have detailed explanations: E0119, E0366, E0367, E0751. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index 77d1bdee5acf1..bc81dd6f286dd 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,9 +1,3 @@ -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 - | -LL | impl !Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` - error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | @@ -12,11 +6,11 @@ LL | impl !Marker1 for dyn Object + Marker2 {} | = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | -LL | impl !Marker2 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` +LL | impl !Marker1 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 @@ -26,6 +20,12 @@ LL | impl !Marker2 for dyn Object + Marker2 {} | = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 + | +LL | impl !Marker2 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1 | diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs index aee6647a78819..665fa15c56e53 100644 --- a/tests/ui/coherence/coherence-orphan.rs +++ b/tests/ui/coherence/coherence-orphan.rs @@ -8,12 +8,13 @@ use lib::TheTrait; struct TheType; impl TheTrait for isize {} -//~^ ERROR E0117 +//~^ ERROR only traits defined in the current crate can be implemented for primitive types impl TheTrait for isize {} impl TheTrait for TheType {} -impl !Send for Vec {} //~ ERROR E0117 +impl !Send for Vec {} +//~^ ERROR only traits defined in the current crate can be implemented for types defined outside of the crate fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negative-impls.rs b/tests/ui/coherence/coherence-overlap-negative-impls.rs deleted file mode 100644 index ffcd56817e5c2..0000000000000 --- a/tests/ui/coherence/coherence-overlap-negative-impls.rs +++ /dev/null @@ -1,44 +0,0 @@ -//@ check-pass -//@ known-bug: #74629 - -// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with -// `T = Test, F = ()`, all bounds are true, making both impls applicable. -// `Test: Fold`, `Test: Fold<()>` are true because of `2`. -// `Is: NotNil` is true because of `auto trait` and lack of negative impl. - -#![feature(negative_impls)] -#![feature(auto_traits)] - -struct Nil; -struct Cons(H); -struct Test; - -trait Fold {} - -impl Fold for Cons -// 0 -where - T: Fold, -{ -} - -impl Fold for Cons -// 1 -where - T: Fold, - private::Is: private::NotNil, -{ -} - -impl Fold for Test {} // 2 - -mod private { - use crate::Nil; - - pub struct Is(T); - pub auto trait NotNil {} - - impl !NotNil for Is {} -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs index 4624faf1e53cf..663a83a665c48 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs @@ -7,9 +7,13 @@ struct Foo; impl Foo { fn foo(self: Pin<&mut Self>) { } + fn foo_sugar(&pin mut self) {} //~ ERROR pinned reference syntax is experimental + fn foo_sugar_const(&pin const self) {} //~ ERROR pinned reference syntax is experimental } -fn foo(x: Pin<&mut Foo>) { +fn foo(mut x: Pin<&mut Foo>) { + Foo::foo_sugar(x.as_mut()); + Foo::foo_sugar_const(x.as_ref()); let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental } @@ -27,4 +31,38 @@ fn baz(mut x: Pin<&mut Foo>) { fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental +#[cfg(any())] +mod not_compiled { + use std::pin::Pin; + + struct Foo; + + impl Foo { + fn foo(self: Pin<&mut Self>) { + } + fn foo_sugar(&pin mut self) {} //~ ERROR pinned reference syntax is experimental + fn foo_sugar_const(&pin const self) {} //~ ERROR pinned reference syntax is experimental + } + + fn foo(mut x: Pin<&mut Foo>) { + Foo::foo_sugar(x.as_mut()); + Foo::foo_sugar_const(x.as_ref()); + let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental + } + + fn foo_sugar(_: &pin mut Foo) {} //~ ERROR pinned reference syntax is experimental + + fn bar(x: Pin<&mut Foo>) { + foo(x); + foo(x); + } + + fn baz(mut x: Pin<&mut Foo>) { + x.foo(); + x.foo(); + } + + fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental +} + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr index dd93a7be1ada1..8ed7543d86e3d 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr @@ -1,5 +1,25 @@ error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:13:14 + --> $DIR/feature-gate-pin_ergonomics.rs:10:19 + | +LL | fn foo_sugar(&pin mut self) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:11:25 + | +LL | fn foo_sugar_const(&pin const self) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:17:14 | LL | let _y: &pin mut Foo = x; | ^^^ @@ -9,7 +29,7 @@ LL | let _y: &pin mut Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:16:18 + --> $DIR/feature-gate-pin_ergonomics.rs:20:18 | LL | fn foo_sugar(_: &pin mut Foo) {} | ^^^ @@ -19,7 +39,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:28:18 + --> $DIR/feature-gate-pin_ergonomics.rs:32:18 | LL | fn baz_sugar(_: &pin const Foo) {} | ^^^ @@ -28,8 +48,58 @@ LL | fn baz_sugar(_: &pin const Foo) {} = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:43:23 + | +LL | fn foo_sugar(&pin mut self) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:44:29 + | +LL | fn foo_sugar_const(&pin const self) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:50:18 + | +LL | let _y: &pin mut Foo = x; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:53:22 + | +LL | fn foo_sugar(_: &pin mut Foo) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:65:22 + | +LL | fn baz_sugar(_: &pin const Foo) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:20:9 + --> $DIR/feature-gate-pin_ergonomics.rs:24:9 | LL | fn bar(x: Pin<&mut Foo>) { | - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -39,15 +109,15 @@ LL | foo(x); | ^ value used here after move | note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary - --> $DIR/feature-gate-pin_ergonomics.rs:12:11 + --> $DIR/feature-gate-pin_ergonomics.rs:14:15 | -LL | fn foo(x: Pin<&mut Foo>) { - | --- ^^^^^^^^^^^^^ this parameter takes ownership of the value +LL | fn foo(mut x: Pin<&mut Foo>) { + | --- ^^^^^^^^^^^^^ this parameter takes ownership of the value | | | in this function error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:25:5 + --> $DIR/feature-gate-pin_ergonomics.rs:29:5 | LL | fn baz(mut x: Pin<&mut Foo>) { | ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -66,7 +136,7 @@ help: consider reborrowing the `Pin` instead of moving it LL | x.as_mut().foo(); | +++++++++ -error: aborting due to 5 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0382, E0658. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/hygiene/generate-mod.stderr b/tests/ui/hygiene/generate-mod.stderr index 32a2e145ca942..58b9c642dabe3 100644 --- a/tests/ui/hygiene/generate-mod.stderr +++ b/tests/ui/hygiene/generate-mod.stderr @@ -1,12 +1,18 @@ error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:35:13 | +LL | type A = $FromOutside; + | ------------ due to this macro variable +... LL | genmod!(FromOutside, Outer); | ^^^^^^^^^^^ not found in this scope error[E0412]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:35:26 | +LL | struct $Outer; + | ------ due to this macro variable +... LL | genmod!(FromOutside, Outer); | ^^^^^ not found in this scope diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr index 3f7a0ae7efa1b..31f25b182f1f5 100644 --- a/tests/ui/hygiene/globs.stderr +++ b/tests/ui/hygiene/globs.stderr @@ -50,6 +50,9 @@ error[E0425]: cannot find function `f` in this scope LL | n!(f); | ----- in this macro invocation ... +LL | $j(); + | -- due to this macro variable +... LL | n!(f); | ^ not found in this scope | @@ -63,6 +66,9 @@ error[E0425]: cannot find function `f` in this scope LL | n!(f); | ----- in this macro invocation ... +LL | $j(); + | -- due to this macro variable +... LL | f | ^ not found in this scope | diff --git a/tests/ui/inference/issue-86094-suggest-add-return-to-coerce-ret-ty.stderr b/tests/ui/inference/issue-86094-suggest-add-return-to-coerce-ret-ty.stderr index 1fea73529a8a2..c61ca699b0d35 100644 --- a/tests/ui/inference/issue-86094-suggest-add-return-to-coerce-ret-ty.stderr +++ b/tests/ui/inference/issue-86094-suggest-add-return-to-coerce-ret-ty.stderr @@ -8,10 +8,6 @@ help: consider specifying the generic arguments | LL | Err::(MyError); | ++++++++++++++ -help: you might have meant to return this to infer its type parameters - | -LL | return Err(MyError); - | ++++++ error[E0282]: type annotations needed --> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:14:9 @@ -23,10 +19,6 @@ help: consider specifying the generic arguments | LL | Ok::<(), E>(()); | +++++++++ -help: you might have meant to return this to infer its type parameters - | -LL | return Ok(()); - | ++++++ error[E0308]: mismatched types --> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:21:20 diff --git a/tests/ui/issues/issue-106755.rs b/tests/ui/issues/issue-106755.rs index 689b1d885ae60..d7e7122ebda16 100644 --- a/tests/ui/issues/issue-106755.rs +++ b/tests/ui/issues/issue-106755.rs @@ -10,10 +10,13 @@ struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR found both positive and negative implementation +impl !Send for TestType {} +//~^ ERROR found both positive and negative implementation +//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not unsafe impl Send for TestType {} //~ ERROR conflicting implementations impl !Send for TestType {} +//~^ ERROR `!Send` impls cannot be specialized fn main() {} diff --git a/tests/ui/issues/issue-106755.stderr b/tests/ui/issues/issue-106755.stderr index 543970340620d..da6b8c5c56325 100644 --- a/tests/ui/issues/issue-106755.stderr +++ b/tests/ui/issues/issue-106755.stderr @@ -8,7 +8,7 @@ LL | impl !Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>` - --> $DIR/issue-106755.rs:15:1 + --> $DIR/issue-106755.rs:17:1 | LL | unsafe impl Send for TestType {} | ------------------------------------------------------ first implementation here @@ -16,7 +16,32 @@ LL | unsafe impl Send for TestType {} LL | unsafe impl Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` -error: aborting due to 2 previous errors +error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not + --> $DIR/issue-106755.rs:13:9 + | +LL | impl !Send for TestType {} + | ^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/issue-106755.rs:9:1 + | +LL | struct TestType(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^ + +error[E0366]: `!Send` impls cannot be specialized + --> $DIR/issue-106755.rs:19:1 + | +LL | impl !Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `i32` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/issue-106755.rs:9:1 + | +LL | struct TestType(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0119, E0751. +Some errors have detailed explanations: E0119, E0366, E0367, E0751. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 07cad7766920f..80b35ff6ad49e 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -10,7 +10,7 @@ error: layout_of(E) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -49,7 +49,7 @@ error: layout_of(E) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -71,7 +71,7 @@ error: layout_of(E) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -112,7 +112,7 @@ error: layout_of(S) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -160,7 +160,7 @@ error: layout_of(U) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -186,7 +186,7 @@ error: layout_of(Result) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -238,7 +238,7 @@ error: layout_of(Result) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -277,7 +277,7 @@ error: layout_of(Result) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -327,7 +327,7 @@ error: layout_of(i32) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -357,7 +357,7 @@ error: layout_of(V) = Layout { abi: Align(2 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -383,7 +383,7 @@ error: layout_of(W) = Layout { abi: Align(2 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -409,7 +409,7 @@ error: layout_of(Y) = Layout { abi: Align(2 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -435,7 +435,7 @@ error: layout_of(P1) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -461,7 +461,7 @@ error: layout_of(P2) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -487,7 +487,7 @@ error: layout_of(P3) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -513,7 +513,7 @@ error: layout_of(P4) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Union( @@ -539,7 +539,7 @@ error: layout_of(P5) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Union { value: Int( I8, @@ -570,7 +570,7 @@ error: layout_of(MaybeUninit) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Union { value: Int( I8, diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index b802b400b18b8..9c3a8662d4f08 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -4,7 +4,7 @@ error: layout_of(A) = Layout { abi: Align(1 bytes), pref: Align(1 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -49,7 +49,7 @@ error: layout_of(A) = Layout { abi: Align(1 bytes), pref: Align(1 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -82,7 +82,7 @@ error: layout_of(B) = Layout { abi: Align(1 bytes), pref: Align(1 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -127,7 +127,7 @@ error: layout_of(B) = Layout { abi: Align(1 bytes), pref: Align(1 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -160,7 +160,7 @@ error: layout_of(C) = Layout { abi: Align(2 bytes), pref: Align(2 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I16, @@ -205,7 +205,7 @@ error: layout_of(C) = Layout { abi: Align(2 bytes), pref: Align(2 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -238,7 +238,7 @@ error: layout_of(P) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -283,7 +283,7 @@ error: layout_of(P) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -316,7 +316,7 @@ error: layout_of(T) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -361,7 +361,7 @@ error: layout_of(T) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 3bdb9c5c143e4..ef7f0cd2d1c34 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -4,7 +4,7 @@ error: layout_of(MissingPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -55,7 +55,7 @@ error: layout_of(MissingPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -93,7 +93,7 @@ error: layout_of(MissingPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -126,7 +126,7 @@ error: layout_of(CommonPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -178,7 +178,7 @@ error: layout_of(CommonPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -217,7 +217,7 @@ error: layout_of(CommonPayloadField) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -267,7 +267,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -318,7 +318,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -356,7 +356,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -405,7 +405,7 @@ error: layout_of(NicheFirst) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -460,7 +460,7 @@ error: layout_of(NicheFirst) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -510,7 +510,7 @@ error: layout_of(NicheFirst) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -532,7 +532,7 @@ error: layout_of(NicheFirst) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -565,7 +565,7 @@ error: layout_of(NicheSecond) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -620,7 +620,7 @@ error: layout_of(NicheSecond) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -670,7 +670,7 @@ error: layout_of(NicheSecond) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -692,7 +692,7 @@ error: layout_of(NicheSecond) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 1d4e443644826..a9081afc50944 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -4,7 +4,7 @@ error: layout_of(Aligned1) = Layout { abi: Align(8 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -43,7 +43,7 @@ error: layout_of(Aligned1) = Layout { abi: Align(8 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -67,7 +67,7 @@ error: layout_of(Aligned1) = Layout { abi: Align(8 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -104,7 +104,7 @@ error: layout_of(Aligned2) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -149,7 +149,7 @@ error: layout_of(Aligned2) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -173,7 +173,7 @@ error: layout_of(Aligned2) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 07153fee02736..b635d1a45bb7a 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -4,7 +4,7 @@ error: layout_of(A) = Layout { abi: Align(1 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -49,7 +49,7 @@ error: layout_of(A) = Layout { abi: Align(1 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -82,7 +82,7 @@ error: layout_of(B) = Layout { abi: Align(1 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -127,7 +127,7 @@ error: layout_of(B) = Layout { abi: Align(1 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -160,7 +160,7 @@ error: layout_of(C) = Layout { abi: Align(2 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I16, @@ -205,7 +205,7 @@ error: layout_of(C) = Layout { abi: Align(2 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -238,7 +238,7 @@ error: layout_of(P) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -283,7 +283,7 @@ error: layout_of(P) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -316,7 +316,7 @@ error: layout_of(T) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -361,7 +361,7 @@ error: layout_of(T) = Layout { abi: Align(4 bytes), pref: Align(4 bytes), }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 33d2eede22090..1ba184bdacefb 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -4,7 +4,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -43,7 +43,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -69,7 +69,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -115,7 +115,7 @@ error: layout_of(MultipleAlignments) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -154,7 +154,7 @@ error: layout_of(MultipleAlignments) = Layout { abi: Align(2 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -180,7 +180,7 @@ error: layout_of(MultipleAlignments) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -206,7 +206,7 @@ error: layout_of(MultipleAlignments) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -252,7 +252,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -291,7 +291,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -317,7 +317,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -363,7 +363,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -406,7 +406,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { abi: Align(4 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -432,7 +432,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { abi: Align(1 bytes), pref: $PREF_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 118b18b224c05..0c27547a6ed8f 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -17,7 +17,7 @@ LL | fn hidden_niche_unsafe_cell() -> Option`, which is not FFI-safe +warning: `extern` block uses type `Option<(usize) is 0..>`, which is not FFI-safe --> $DIR/clashing-extern-fn.rs:502:54 | LL | fn pt_non_zero_usize_opt_full_range() -> Option; diff --git a/tests/ui/macros/macro-parameter-span.stderr b/tests/ui/macros/macro-parameter-span.stderr index 247750a8ad705..44c8c56dff999 100644 --- a/tests/ui/macros/macro-parameter-span.stderr +++ b/tests/ui/macros/macro-parameter-span.stderr @@ -1,6 +1,9 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/macro-parameter-span.rs:11:9 | +LL | $id + | --- due to this macro variable +... LL | x | ^ not found in this scope diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr index ce7694ecb1da3..d9646760cea92 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -338,6 +338,9 @@ LL | no_curly__no_rhs_dollar__no_round!(a); error[E0425]: cannot find value `a` in this scope --> $DIR/syntax-errors.rs:152:37 | +LL | ( $i:ident ) => { count($i) }; + | -- due to this macro variable +... LL | no_curly__rhs_dollar__no_round!(a); | ^ not found in this scope diff --git a/tests/ui/methods/ident-from-macro-expansion.rs b/tests/ui/methods/ident-from-macro-expansion.rs new file mode 100644 index 0000000000000..38d2fee0e53c0 --- /dev/null +++ b/tests/ui/methods/ident-from-macro-expansion.rs @@ -0,0 +1,18 @@ +macro_rules! dot { + ($id:ident) => { + ().$id(); + } +} + +macro_rules! dispatch { + ($id:ident) => { + <()>::$id(); + } +} + +fn main() { + dot!(hello); + //~^ ERROR no method named `hello` found for unit type `()` in the current scope + dispatch!(hello); + //~^ ERROR no function or associated item named `hello` found for unit type `()` in the current scope +} diff --git a/tests/ui/methods/ident-from-macro-expansion.stderr b/tests/ui/methods/ident-from-macro-expansion.stderr new file mode 100644 index 0000000000000..b596ce29f6fee --- /dev/null +++ b/tests/ui/methods/ident-from-macro-expansion.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `hello` found for unit type `()` in the current scope + --> $DIR/ident-from-macro-expansion.rs:14:10 + | +LL | ().$id(); + | --- due to this macro variable +... +LL | dot!(hello); + | ^^^^^ method not found in `()` + +error[E0599]: no function or associated item named `hello` found for unit type `()` in the current scope + --> $DIR/ident-from-macro-expansion.rs:16:15 + | +LL | <()>::$id(); + | --- due to this macro variable +... +LL | dispatch!(hello); + | ^^^^^ function or associated item not found in `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 42fcaee2d4aa4..c11acc98637df 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -4,7 +4,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -49,7 +49,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -92,7 +92,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -143,7 +143,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -181,7 +181,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -230,7 +230,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -269,7 +269,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -299,7 +299,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index bb2c6e70dc7ab..a7888155deaf7 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -4,7 +4,7 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -49,7 +49,7 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -92,7 +92,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -143,7 +143,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -181,7 +181,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -230,7 +230,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -269,7 +269,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -299,7 +299,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 42fcaee2d4aa4..c11acc98637df 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -4,7 +4,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -49,7 +49,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -92,7 +92,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -143,7 +143,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -181,7 +181,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -230,7 +230,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -269,7 +269,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -299,7 +299,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 42fcaee2d4aa4..c11acc98637df 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -4,7 +4,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -49,7 +49,7 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -92,7 +92,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -143,7 +143,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -181,7 +181,7 @@ error: layout_of(TwoVariants) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I32, @@ -230,7 +230,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -269,7 +269,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -299,7 +299,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index f852212deb908..f63574182c25f 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -4,7 +4,7 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -49,7 +49,7 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I8, @@ -92,7 +92,7 @@ error: layout_of(TwoVariantsU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -143,7 +143,7 @@ error: layout_of(TwoVariantsU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -181,7 +181,7 @@ error: layout_of(TwoVariantsU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: ScalarPair( + backend_repr: ScalarPair( Initialized { value: Int( I8, @@ -230,7 +230,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -269,7 +269,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -299,7 +299,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { diff --git a/tests/ui/return/tail-expr-as-potential-return.rs b/tests/ui/return/tail-expr-as-potential-return.rs index 11ecddb049b57..2e638f1897c22 100644 --- a/tests/ui/return/tail-expr-as-potential-return.rs +++ b/tests/ui/return/tail-expr-as-potential-return.rs @@ -60,7 +60,6 @@ fn method() -> Option { Receiver.generic(); //~^ ERROR type annotations needed //~| HELP consider specifying the generic argument - //~| HELP you might have meant to return this to infer its type parameters } None diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr index 756de2b5a1668..8105b2df3fea6 100644 --- a/tests/ui/return/tail-expr-as-potential-return.stderr +++ b/tests/ui/return/tail-expr-as-potential-return.stderr @@ -57,10 +57,6 @@ help: consider specifying the generic argument | LL | Receiver.generic::(); | +++++ -help: you might have meant to return this to infer its type parameters - | -LL | return Receiver.generic(); - | ++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs index 4049c4ea14c5b..14771be8982dd 100644 --- a/tests/ui/specialization/defaultimpl/validation.rs +++ b/tests/ui/specialization/defaultimpl/validation.rs @@ -6,12 +6,17 @@ struct Z; default impl S {} //~ ERROR inherent impls cannot be `default` -default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default -//~^ ERROR `S` cannot be sent between threads safely -default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default - //~^ ERROR negative impls cannot be default impls +default unsafe impl Send for S {} +//~^ ERROR impls of auto traits cannot be default + +default impl !Send for Z {} +//~^ ERROR impls of auto traits cannot be default +//~| ERROR negative impls cannot be default impls +//~| ERROR `!Send` impl requires `Z: Send` but the struct it is implemented for does not trait Tr {} -default impl !Tr for S {} //~ ERROR negative impls cannot be default impls + +default impl !Tr for S {} +//~^ ERROR negative impls cannot be default impls fn main() {} diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr index f56f16162a27f..d034386b842f3 100644 --- a/tests/ui/specialization/defaultimpl/validation.stderr +++ b/tests/ui/specialization/defaultimpl/validation.stderr @@ -26,22 +26,20 @@ LL | default unsafe impl Send for S {} | | | default because of this -error[E0277]: `S` cannot be sent between threads safely - --> $DIR/validation.rs:9:1 +error[E0367]: `!Send` impl requires `Z: Send` but the struct it is implemented for does not + --> $DIR/validation.rs:12:1 | -LL | default unsafe impl Send for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `S` cannot be sent between threads safely - | - = help: the trait `Send` is not implemented for `S` - = help: the trait `Send` is implemented for `S` - = help: see issue #48214 -help: add `#![feature(trivial_bounds)]` to the crate attributes to enable +LL | default impl !Send for Z {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ | -LL + #![feature(trivial_bounds)] +note: the implementor must specify the same requirement + --> $DIR/validation.rs:5:1 | +LL | struct Z; + | ^^^^^^^^ error: impls of auto traits cannot be default - --> $DIR/validation.rs:11:15 + --> $DIR/validation.rs:12:15 | LL | default impl !Send for Z {} | ------- ^^^^ auto trait @@ -49,18 +47,18 @@ LL | default impl !Send for Z {} | default because of this error[E0750]: negative impls cannot be default impls - --> $DIR/validation.rs:11:1 + --> $DIR/validation.rs:12:1 | LL | default impl !Send for Z {} | ^^^^^^^ ^ error[E0750]: negative impls cannot be default impls - --> $DIR/validation.rs:15:1 + --> $DIR/validation.rs:19:1 | LL | default impl !Tr for S {} | ^^^^^^^ ^ error: aborting due to 6 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0750. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0367, E0750. +For more information about an error, try `rustc --explain E0367`. diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs index 550d370829539..244f21c7ba905 100644 --- a/tests/ui/specialization/specialization-overlap-negative.rs +++ b/tests/ui/specialization/specialization-overlap-negative.rs @@ -6,6 +6,8 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR E0751 +impl !Send for TestType {} +//~^ ERROR found both positive and negative implementation of trait `Send` for type `TestType<_>` +//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr index a8e99953e2b65..4874e897726fc 100644 --- a/tests/ui/specialization/specialization-overlap-negative.stderr +++ b/tests/ui/specialization/specialization-overlap-negative.stderr @@ -16,6 +16,19 @@ LL | unsafe impl Send for TestType {} LL | impl !Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to 1 previous error; 1 warning emitted +error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not + --> $DIR/specialization-overlap-negative.rs:9:9 + | +LL | impl !Send for TestType {} + | ^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/specialization-overlap-negative.rs:6:1 + | +LL | struct TestType(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0751`. +Some errors have detailed explanations: E0367, E0751. +For more information about an error, try `rustc --explain E0367`. diff --git a/tests/ui/structs/ident-from-macro-expansion.rs b/tests/ui/structs/ident-from-macro-expansion.rs new file mode 100644 index 0000000000000..56d31a4256168 --- /dev/null +++ b/tests/ui/structs/ident-from-macro-expansion.rs @@ -0,0 +1,19 @@ +struct Foo { + inner: Inner, +} + +struct Inner { + y: i32, +} + +macro_rules! access { + ($expr:expr, $ident:ident) => { + $expr.$ident + } +} + +fn main() { + let k = Foo { inner: Inner { y: 0 } }; + access!(k, y); + //~^ ERROR no field `y` on type `Foo` +} diff --git a/tests/ui/structs/ident-from-macro-expansion.stderr b/tests/ui/structs/ident-from-macro-expansion.stderr new file mode 100644 index 0000000000000..be2ab7c2e9966 --- /dev/null +++ b/tests/ui/structs/ident-from-macro-expansion.stderr @@ -0,0 +1,14 @@ +error[E0609]: no field `y` on type `Foo` + --> $DIR/ident-from-macro-expansion.rs:17:16 + | +LL | $expr.$ident + | ------ due to this macro variable +... +LL | access!(k, y); + | ^ unknown field + | + = note: available field is: `inner` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.rs b/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.rs new file mode 100644 index 0000000000000..cd675a5efd162 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.rs @@ -0,0 +1,22 @@ +#![feature(auto_traits, negative_impls)] + +auto trait Foo {} + +struct AdditionalLt<'a, T>(&'a (), T); +impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {} +//~^ ERROR `!Foo` impl requires `T: 'a` but the struct it is implemented for does not + +struct AdditionalBound(T); +trait Bound {} +impl !Foo for AdditionalBound {} +//~^ ERROR `!Foo` impl requires `T: Bound` but the struct it is implemented for does not + +struct TwoParam(T, U); +impl !Foo for TwoParam {} +//~^ ERROR `!Foo` impls cannot be specialized + +struct ConcreteParam(T); +impl !Foo for ConcreteParam {} +//~^ ERROR `!Foo` impls cannot be specialized + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.stderr new file mode 100644 index 0000000000000..ef783e9015592 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-validity-error.stderr @@ -0,0 +1,54 @@ +error[E0367]: `!Foo` impl requires `T: 'a` but the struct it is implemented for does not + --> $DIR/negated-auto-traits-validity-error.rs:6:13 + | +LL | impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {} + | ^^ + | +note: the implementor must specify the same requirement + --> $DIR/negated-auto-traits-validity-error.rs:5:1 + | +LL | struct AdditionalLt<'a, T>(&'a (), T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `!Foo` impl requires `T: Bound` but the struct it is implemented for does not + --> $DIR/negated-auto-traits-validity-error.rs:11:9 + | +LL | impl !Foo for AdditionalBound {} + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/negated-auto-traits-validity-error.rs:9:1 + | +LL | struct AdditionalBound(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0366]: `!Foo` impls cannot be specialized + --> $DIR/negated-auto-traits-validity-error.rs:15:1 + | +LL | impl !Foo for TwoParam {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `T` is mentioned multiple times +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/negated-auto-traits-validity-error.rs:14:1 + | +LL | struct TwoParam(T, U); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0366]: `!Foo` impls cannot be specialized + --> $DIR/negated-auto-traits-validity-error.rs:19:1 + | +LL | impl !Foo for ConcreteParam {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `i32` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/negated-auto-traits-validity-error.rs:18:1 + | +LL | struct ConcreteParam(T); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0366, E0367. +For more information about an error, try `rustc --explain E0366`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-validity.rs b/tests/ui/traits/negative-impls/negated-auto-traits-validity.rs new file mode 100644 index 0000000000000..76996b5593e60 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-validity.rs @@ -0,0 +1,22 @@ +//@ check-pass + +#![feature(auto_traits, negative_impls)] + +auto trait Foo {} +auto trait Bar {} + +struct NeedsOutlives<'a, T>(&'a T); + +impl<'a, T: 'a> !Foo for NeedsOutlives<'a, T> {} + +// Leaving out the lifetime bound +impl<'a, T> !Bar for NeedsOutlives<'a, T> {} + +struct NeedsSend(T); + +impl !Foo for NeedsSend {} + +// Leaving off the trait bound +impl !Bar for NeedsSend {} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/dyn-to-dyn-star.rs b/tests/ui/traits/trait-upcasting/dyn-to-dyn-star.rs new file mode 100644 index 0000000000000..5936c93efad31 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/dyn-to-dyn-star.rs @@ -0,0 +1,19 @@ +// While somewhat nonsensical, this is a cast from a wide pointer to a thin pointer. +// Thus, we don't need to check an unsize goal here; there isn't any vtable casting +// happening at all. + +// Regression test for . + +//@ check-pass + +#![allow(incomplete_features)] +#![feature(dyn_star)] + +trait Foo {} +trait Bar {} + +fn cast(x: *const dyn Foo) { + x as *const dyn* Bar; +} + +fn main() {} diff --git a/tests/ui/type/pattern_types/nested.rs b/tests/ui/type/pattern_types/nested.rs index 9ca9c7923dedd..0d8cd22190e55 100644 --- a/tests/ui/type/pattern_types/nested.rs +++ b/tests/ui/type/pattern_types/nested.rs @@ -18,10 +18,12 @@ const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: not a valid base type for range patterns //~| ERROR: mismatched types const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: not a valid base type for range patterns //~| ERROR: mismatched types const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr index b753b0a9c9baa..f79d12bc3f376 100644 --- a/tests/ui/type/pattern_types/nested.stderr +++ b/tests/ui/type/pattern_types/nested.stderr @@ -1,96 +1,184 @@ -error: `(u32) is 1..=` is not a valid base type for range patterns - --> $DIR/nested.rs:10:34 +error[E0308]: mismatched types + --> $DIR/nested.rs:10:63 | LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected `(u32) is 1..`, found integer | -note: range patterns only support integers - --> $DIR/nested.rs:10:63 + = note: expected pattern type `(u32) is 1..` + found type `{integer}` + +error[E0277]: `(u32) is 1..` is not a valid base type for range patterns + --> $DIR/nested.rs:10:34 | LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); - | ^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `(u32) is 1..` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others -error: `(i32) is 1..=` is not a valid base type for range patterns +error[E0277]: `(i32) is 1..` is not a valid base type for range patterns --> $DIR/nested.rs:15:35 | LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: range patterns only support integers - --> $DIR/nested.rs:15:64 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others + +error[E0308]: mismatched types + --> $DIR/nested.rs:15:67 | LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); - | ^^^^^ + | ^^ expected `(i32) is 1..`, found integer + | + = note: expected pattern type `(i32) is 1..` + found type `{integer}` -error: `(i32) is 1..=` is not a valid base type for range patterns +error[E0277]: `(i32) is 1..` is not a valid base type for range patterns --> $DIR/nested.rs:19:35 | LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: range patterns only support integers - --> $DIR/nested.rs:19:64 - | -LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); - | ^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others -error: `()` is not a valid base type for range patterns - --> $DIR/nested.rs:23:35 +error[E0308]: mismatched types + --> $DIR/nested.rs:19:66 | -LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); - | ^^ +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^ + | | + | expected `(i32) is 1..`, found integer + | arguments to this function are incorrect | -note: range patterns only support integers - --> $DIR/nested.rs:23:41 + = note: expected pattern type `(i32) is 1..` + found type `{integer}` +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/nested.rs:19:66 | -LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); - | ^^^ +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^ this argument influences the return type of `RangeSub` +note: method defined here + --> $SRC_DIR/core/src/pat.rs:LL:COL -error: `f32` is not a valid base type for range patterns - --> $DIR/nested.rs:27:35 - | -LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); - | ^^^ - | -note: range patterns only support integers - --> $DIR/nested.rs:27:42 +error[E0277]: `(i32) is 1..` is not a valid base type for range patterns + --> $DIR/nested.rs:19:66 | -LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); - | ^^^^^^^^^^ +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `(i32) is 1..` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others -error[E0308]: mismatched types - --> $DIR/nested.rs:10:63 +error[E0277]: `()` is not a valid base type for range patterns + --> $DIR/nested.rs:24:35 | -LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); - | ^ expected `(u32) is 1..=`, found integer - | - = note: expected pattern type `(u32) is 1..=` - found type `{integer}` +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `()` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others error[E0308]: mismatched types - --> $DIR/nested.rs:15:67 - | -LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); - | ^^ expected `(i32) is 1..=`, found integer + --> $DIR/nested.rs:24:43 | - = note: expected pattern type `(i32) is 1..=` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/nested.rs:19:66 +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^ + | | + | expected `()`, found integer + | arguments to this function are incorrect | -LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); - | ^ expected `(i32) is 1..=`, found integer +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/nested.rs:24:43 | - = note: expected pattern type `(i32) is 1..=` - found type `{integer}` +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^ this argument influences the return type of `RangeSub` +note: method defined here + --> $SRC_DIR/core/src/pat.rs:LL:COL -error[E0308]: mismatched types - --> $DIR/nested.rs:23:43 +error[E0277]: `()` is not a valid base type for range patterns + --> $DIR/nested.rs:24:43 | LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); - | ^ expected `()`, found integer + | ^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `()` + = help: the following other types implement trait `core::pat::RangePattern`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others + +error[E0277]: `f32` is not a valid base type for range patterns + --> $DIR/nested.rs:29:49 + | +LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); + | ^^^ only integer types and `char` are supported + | + = help: the trait `core::pat::RangePattern` is not implemented for `f32` + = help: the following other types implement trait `core::pat::RangePattern`: + i128 + i16 + i32 + i64 + i8 + isize + u128 + u16 + and 4 others -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 690592ba0b8da..cb24a303404c6 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -4,7 +4,7 @@ error: layout_of(NonZero) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -44,13 +44,13 @@ error: layout_of(NonZero) = Layout { LL | type X = std::num::NonZeroU32; | ^^^^^^ -error: layout_of((u32) is 1..=) = Layout { +error: layout_of((u32) is 1..) = Layout { size: Size(4 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -83,13 +83,13 @@ error: layout_of((u32) is 1..=) = Layout { LL | type Y = pattern_type!(u32 is 1..); | ^^^^^^ -error: layout_of(Option<(u32) is 1..=>) = Layout { +error: layout_of(Option<(u32) is 1..>) = Layout { size: Size(4 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -129,7 +129,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -151,7 +151,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -203,7 +203,7 @@ error: layout_of(Option>) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -243,7 +243,7 @@ error: layout_of(Option>) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Memory { + backend_repr: Memory { sized: true, }, fields: Arbitrary { @@ -265,7 +265,7 @@ error: layout_of(Option>) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, @@ -317,7 +317,7 @@ error: layout_of(NonZeroU32New) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Scalar( + backend_repr: Scalar( Initialized { value: Int( I32, diff --git a/tests/ui/type/pattern_types/range_patterns_unusable.stderr b/tests/ui/type/pattern_types/range_patterns_unusable.stderr index 8377d417452bb..7daa41d708179 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable.stderr @@ -4,7 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let _: Option = unsafe { std::mem::transmute(z) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `Option<(u32) is 1..=>` (32 bits) + = note: source type: `Option<(u32) is 1..>` (32 bits) = note: target type: `Option` (64 bits) error: aborting due to 1 previous error diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs index ece4009e1e7d8..6125063699be9 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs @@ -11,5 +11,5 @@ type Z = Option; fn main() { let x: Y = unsafe { std::mem::transmute(42_u32) }; - let x = x + 1_u32; //~ ERROR cannot add `u32` to `(u32) is 1..=` + let x = x + 1_u32; //~ ERROR cannot add `u32` to `(u32) is 1..` } diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr index 373615e3714e5..a64f1db31766f 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr @@ -1,10 +1,10 @@ -error[E0369]: cannot add `u32` to `(u32) is 1..=` +error[E0369]: cannot add `u32` to `(u32) is 1..` --> $DIR/range_patterns_unusable_math.rs:14:15 | LL | let x = x + 1_u32; | - ^ ----- u32 | | - | (u32) is 1..= + | (u32) is 1.. error: aborting due to 1 previous error diff --git a/tests/ui/type/pattern_types/reverse_range.rs b/tests/ui/type/pattern_types/reverse_range.rs index 6a245615f1ac0..e698e9dd541d5 100644 --- a/tests/ui/type/pattern_types/reverse_range.rs +++ b/tests/ui/type/pattern_types/reverse_range.rs @@ -1,14 +1,11 @@ //! Check that the range start must be smaller than the range end -//@ known-bug: unknown -//@ failure-status: 101 -//@ normalize-stderr: "note: .*\n\n" -> "" -//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" -//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@ rustc-env:RUST_BACKTRACE=0 - -#![feature(pattern_types)] +#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)] #![feature(pattern_type_macro)] use std::pat::pattern_type; const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) }; +//~^ NOTE: exclusive range end at minimum value of type +//~| ERROR: evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/type/pattern_types/reverse_range.stderr b/tests/ui/type/pattern_types/reverse_range.stderr index b714ca7d9ab96..90f8ef3261a0b 100644 --- a/tests/ui/type/pattern_types/reverse_range.stderr +++ b/tests/ui/type/pattern_types/reverse_range.stderr @@ -1,17 +1,9 @@ -error[E0601]: `main` function not found in crate `reverse_range` - --> $DIR/reverse_range.rs:14:78 +error[E0080]: evaluation of constant value failed + --> $DIR/reverse_range.rs:7:36 | LL | const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) }; - | ^ consider adding a `main` function to `$DIR/reverse_range.rs` + | ^ evaluation panicked: exclusive range end at minimum value of type - -assertion failed: end <= max_value -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [eval_to_allocation_raw] const-evaluating + checking `NONE` -#1 [eval_to_const_value_raw] simplifying constant for the type system `NONE` -... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs index 77a4e72f6755a..5a6a688e1b305 100644 --- a/tests/ui/type/pattern_types/validity.rs +++ b/tests/ui/type/pattern_types/validity.rs @@ -1,6 +1,6 @@ //! Check that pattern types have their validity checked -#![feature(pattern_types)] +#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)] #![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/unsafe-fields/unsafe-fields.rs b/tests/ui/unsafe-fields/unsafe-fields.rs index 637471582d7e4..cb86479bb20d3 100644 --- a/tests/ui/unsafe-fields/unsafe-fields.rs +++ b/tests/ui/unsafe-fields/unsafe-fields.rs @@ -17,7 +17,7 @@ fn f(a: A) { } struct WithInvalidUnsafeField { - unsafe unsafe_noncopy_field: Vec, //~ ERROR + unsafe unsafe_noncopy_field: Vec, } struct WithManuallyDropUnsafeField { diff --git a/tests/ui/unsafe-fields/unsafe-fields.stderr b/tests/ui/unsafe-fields/unsafe-fields.stderr index a1c5d2b44cdf1..d0e2dc16a13d5 100644 --- a/tests/ui/unsafe-fields/unsafe-fields.stderr +++ b/tests/ui/unsafe-fields/unsafe-fields.stderr @@ -1,15 +1,3 @@ -error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be unsafe - --> $DIR/unsafe-fields.rs:20:5 - | -LL | unsafe unsafe_noncopy_field: Vec, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: unsafe fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` -help: wrap the field type in `ManuallyDrop<...>` - | -LL | unsafe unsafe_noncopy_field: std::mem::ManuallyDrop>, - | +++++++++++++++++++++++ + - error[E0133]: use of unsafe field is unsafe and requires unsafe block --> $DIR/unsafe-fields.rs:15:30 | @@ -69,7 +57,6 @@ LL | &raw const self.unsafe_field | = note: unsafe fields may carry library invariants -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0133, E0740. -For more information about an error, try `rustc --explain E0133`. +For more information about this error, try `rustc --explain E0133`.