diff --git a/RELEASES.md b/RELEASES.md index 77b58ce2bcf25..cd1f3ca7c3800 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -116,6 +116,7 @@ Compatibility Notes - [`semicolon_in_expressions_from_macros`: Lint on non-local macros too](https://github.com/rust-lang/rust/pull/159222) - [Split non-local `semicolon_in_expressions_from_macros` into a separate lint](https://github.com/rust-lang/rust/pull/159700) - In Cargo, incremental compilation is now disabled by default when running in CI. CI is detected via the `CI` environment variable. [#17220](https://github.com/rust-lang/cargo/pull/17220) +- [The Rust Reference no longer recommends using a single pattern to match a union alongside another value, such as in a manually-written tagged union](https://github.com/rust-lang/reference/pull/2303). This was because it was found that such code would, in some circumstances, result in the compiler reading the contents of the union before checking if the rest of the scrutinee matches the rest of the pattern. This can cause undefined behavior in code similar to what the reference previously recommended. diff --git a/compiler/rustc_errors/src/dedup_hash.rs b/compiler/rustc_errors/src/dedup_hash.rs new file mode 100644 index 0000000000000..b8b2da69bc1d3 --- /dev/null +++ b/compiler/rustc_errors/src/dedup_hash.rs @@ -0,0 +1,63 @@ +use std::hash::Hash; + +use rustc_data_structures::stable_hash::StableHasher; +use rustc_serialize::Encoder; +use rustc_span::def_id::{CrateNum, DefId, DefIndex}; +use rustc_span::{ByteSymbol, ExpnId, Span, SpanEncoder, Symbol, SyntaxContext}; + +/// Hasher used to determine if two diagnostics are the same and should be deduplicated. Used by +/// `DiagCtxtInner::emitted_diagnostics`. It's a stable hash with one special behaviour: parents of +/// spans within the diagnostics are ignored so that incremental and non-incremental compilation +/// get the same behaviour. +/// +/// Although this has nothing to do with encoding data to/from file, it is implemented on top of +/// `Encoder`/`SpanEncoder` because they provide traversals of all the relevant types used within +/// diagnostics. There is no corresponding decoder. +pub(crate) struct DedupHashEncoder(pub(crate) StableHasher); + +macro_rules! encoder_methods { + ($($name:ident($ty:ty);)*) => { + $( + #[inline] + fn $name(&mut self, value: $ty) { + value.hash(&mut self.0) + } + )* + } +} + +impl Encoder for DedupHashEncoder { + encoder_methods! { + emit_usize(usize); + emit_u128(u128); + emit_u64(u64); + emit_u32(u32); + emit_u16(u16); + emit_u8(u8); + + emit_isize(isize); + emit_i128(i128); + emit_i64(i64); + emit_i32(i32); + emit_i16(i16); + + emit_raw_bytes(&[u8]); + } +} + +impl SpanEncoder for DedupHashEncoder { + fn encode_span(&mut self, span: Span) { + // The raison d'être of `DedupHashEncoder` is to ignore `parent` here. + span.with_parent(None).hash(&mut self.0); + } + + encoder_methods! { + encode_symbol(Symbol); + encode_byte_symbol(ByteSymbol); + encode_expn_id(ExpnId); + encode_syntax_context(SyntaxContext); + encode_crate_num(CrateNum); + encode_def_index(DefIndex); + encode_def_id(DefId); + } +} diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 362df06c404db..65dc8042fd409 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,9 +12,11 @@ use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg}; use rustc_hashes::Hash128; use rustc_lint_defs::Applicability; use rustc_macros::{Decodable, Encodable}; +use rustc_serialize::Encodable; use rustc_span::{Span, Spanned, Symbol}; use tracing::debug; +use crate::dedup_hash::DedupHashEncoder; use crate::{ CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, MultiSpan, StashKey, Style, Sublevel, Substitution, SubstitutionPart, SuggestionStyle, @@ -298,20 +300,22 @@ impl DiagInner { emitted_at: _, // ignore } = self; - let hashed_parts = ( - std::mem::discriminant(level), // ignore the field within `Warning` - messages, - code, - span, - children, - suggestions, - args.as_slice(), - is_lint, - ); + let mut e = DedupHashEncoder(StableHasher::new()); - let mut hasher = StableHasher::new(); - hashed_parts.hash(&mut hasher); - hasher.finish() + // We use `discriminant` because we want to ignore the field within `Warning`. + // `Encoder`/`SpanEncoder` can't traverse a `Discriminant` so we hash it directly. + std::mem::discriminant(level).hash(&mut e.0); + + // All the other fields are hashed via `encode`. + messages.encode(&mut e); + code.encode(&mut e); + span.encode(&mut e); + children.encode(&mut e); + suggestions.encode(&mut e); + args.encode(&mut e); + is_lint.encode(&mut e); + + e.0.finish() } } @@ -324,6 +328,16 @@ pub struct Subdiag { pub span: MultiSpan, } +impl Subdiag { + /// Hash used to determine if two subdiagnostics are the same. Used by + /// `DiagCtxtInner::emitted_diagnostics`. + pub(crate) fn dedup_hash(&self) -> Hash128 { + let mut e = DedupHashEncoder(StableHasher::new()); + self.encode(&mut e); + e.0.finish() + } +} + /// Used for emitting structured error messages and other diagnostic information. /// Wraps a `DiagInner`, adding some useful things. /// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4cc5d5c230d15..a1ccefefbcb2a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -44,7 +44,6 @@ use emitter::{DynEmitter, Emitter}; use rustc_ast::attr::version::RustcVersion; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::stable_hash::StableHasher; use rustc_data_structures::sync::{DynSend, Lock}; pub use rustc_error_messages::{ DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg, @@ -70,6 +69,7 @@ use crate::timings::TimingRecord; pub mod annotate_snippet_emitter_writer; pub mod codes; mod decorate_diag; +mod dedup_hash; mod diagnostic; mod diagnostic_impls; pub mod emitter; @@ -1321,21 +1321,18 @@ impl DiagCtxtInner { debug!(?diagnostic); debug!(?self.emitted_diagnostics); - let not_yet_emitted = |sub: &mut Subdiag| { + let show_sub = |sub: &Subdiag| { debug!(?sub); match sub.level { Sublevel::Error | Sublevel::Warning | Sublevel::Note | Sublevel::Help => { - return true; + true + } + Sublevel::OnceNote | Sublevel::OnceHelp => { + self.emitted_diagnostics.insert(sub.dedup_hash()) } - Sublevel::OnceNote | Sublevel::OnceHelp => {} } - let mut hasher = StableHasher::new(); - sub.hash(&mut hasher); - let diagnostic_hash = hasher.finish(); - debug!(?diagnostic_hash); - self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.retain_mut(not_yet_emitted); + diagnostic.children.retain(show_sub); if already_emitted { let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`"; diagnostic.sub(Sublevel::Note, msg, MultiSpan::new()); diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index 7e5e794b75f78..b003a358f9589 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -1741,7 +1741,7 @@ pub(crate) struct UnusedGenericParameter { pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[label("`{$param_name}` is named here, but is likely unused in the containing type")] + #[label("`{$param_name}` is named here, but is not used in the type that wraps it")] pub usage_spans: Vec, #[subdiagnostic] pub help: UnusedGenericParameterHelp, diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 20c1c5c16c95c..738521b2005e0 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -929,10 +929,12 @@ impl<'tcx> TyEncoder<'tcx> for CacheEncoder<'tcx> { macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { - #[inline] - $(fn $name(&mut self, value: $ty) { - self.encoder.$name(value) - })* + $( + #[inline] + fn $name(&mut self, value: $ty) { + self.encoder.$name(value) + } + )* } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 81a41be1c62da..b5fa022a527e5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -725,6 +725,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } CastKind::Transmute | CastKind::Subtype => { let value = self.eval_to_const(value)?; + if value.is_immediate_uninit() { + return Some(ImmTy::uninit(ty).into()); + } // `offset` for immediates generally only supports projections that match the // type of the immediate. However, as a HACK, we exploit that it can also do // limited transmutes: it only works between types with the same layout, and diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index 1a343c737ad45..c2cf50b40a478 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -101,6 +101,7 @@ pub(crate) fn opts() -> TargetOptions { emit_debug_gdb_scripts: false, requires_uwtable: true, eh_frame_header: false, + has_thread_local: true, debuginfo_kind: DebuginfoKind::Dwarf, // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e1043d53fa6fc..8f2d496f95b25 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -521,8 +521,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< predicates: vec![], recursion_limit: usize::min(16, tcx.recursion_limit().0), }; - let _ = self - .with_disabled_next_solver_overflow_fcw(|| self.visit_proof_tree(goal, &mut visitor)); + + // HACK: avoid computing goal chains for dependencies by relying on the fact that + // `cargo` passes `lint_cap=allow` to deps. This should mitigate some of the perf/rss + // regression when compiling crates whose deps trigger a large number of these FCWs. + if !matches!(tcx.sess.opts.lint_cap, Some(rustc_lint_defs::Level::Allow)) { + let _ = self.with_disabled_next_solver_overflow_fcw(|| { + self.visit_proof_tree(goal, &mut visitor) + }); + } + tcx.emit_node_span_lint( RECURSION_DEPTH_EXCEEDING_LIMIT, CRATE_HIR_ID, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 9430b6c4b3307..ef9caca003ef2 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -2,7 +2,8 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::at::At; use rustc_infer::traits::solve::Goal; use rustc_infer::traits::{ - FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, TraitErrors, + FromSolverError, Normalized, Obligation, PredicateObligation, PredicateObligations, + TraitEngine, TraitErrors, }; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ @@ -11,23 +12,32 @@ use rustc_middle::ty::{ }; use rustc_next_trait_solver::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; -use thin_vec::ThinVec; +use thin_vec::{ThinVec, thin_vec}; use super::{FulfillmentCtxt, NextSolverError}; use crate::solve::{Certainty, SolverDelegate}; use crate::traits::{BoundVarReplacer, ScrubbedTraitError}; -/// see `normalize_with_universes`. +/// Normalize a value, deferring ambiguity and errors to fulfillment. pub fn normalize<'tcx, T>(at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>) -> Normalized<'tcx, T> where T: TypeFoldable>, { - normalize_with_universes(at, value, vec![]) + match normalize_with_universes(at, value.clone(), vec![]) { + Ok(normalized) => normalized, + Err(_) => { + let mut replacer = + ReplaceAliasWithInfer { at, obligations: Default::default(), universes: vec![] }; + let value = at.infcx.deeply_resolve_ignoring_regions(value.skip_normalization()); + let value = value.fold_with(&mut replacer); + Normalized { value, obligations: replacer.obligations } + } + } } /// Like `deeply_normalize`, but we handle ambiguity and inference variables in this routine. /// The behavior should be same as the old solver. -/// For error, we return an infer var plus the failed obligation. +/// On error, return the failed obligation. /// For ambiguity, we have two cases: /// - has_escaping_bound_vars: return the original alias. /// - otherwise: return the normalized result. It can be (partially) inferred @@ -36,7 +46,7 @@ fn normalize_with_universes<'tcx, T>( at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>, universes: Vec>, -) -> Normalized<'tcx, T> +) -> Result, PredicateObligation<'tcx>> where T: TypeFoldable>, { @@ -45,19 +55,25 @@ where let value = infcx.deeply_resolve_ignoring_regions(value); if !infcx.tcx.renormalize_rigid_aliases() && !value.has_non_rigid_aliases() { - return Normalized { value, obligations: Default::default() }; + return Ok(Normalized { value, obligations: Default::default() }); } - let original_value = value.clone(); let mut stalled_goals = vec![]; - let mut folder = NormalizationFolder::new(infcx, universes.clone(), |alias_term| { + let mut folder = NormalizationFolder::new(infcx, universes, |alias_term| { let delegate = <&SolverDelegate<'tcx>>::from(infcx); let infer_term = delegate.next_term_var_of_alias_kind(alias_term, at.cause.span); let predicate = ty::ProjectionClause { projection_term: alias_term, term: infer_term }; let goal = Goal::new(infcx.tcx, at.param_env, predicate); let result = match delegate.evaluate_root_goal(goal, at.cause.span, None) { Ok(result) => result, - Err(err) => return Err(err), + Err(_) => { + return Err(Obligation::new( + infcx.tcx, + at.cause.clone(), + goal.param_env, + goal.predicate, + )); + } }; let normalized = infcx.deeply_resolve_ignoring_regions(infer_term); let normalization_was_ambiguous = match result.certainty { @@ -69,19 +85,12 @@ where }; Ok((normalized, normalization_was_ambiguous)) }); - if let Ok(value) = value.try_fold_with(&mut folder) { - let obligations = stalled_goals - .into_iter() - .map(|goal| { - Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) - }) - .collect(); - Normalized { value, obligations } - } else { - let mut replacer = ReplaceAliasWithInfer { at, obligations: Default::default(), universes }; - let value = original_value.fold_with(&mut replacer); - Normalized { value, obligations: replacer.obligations } - } + let value = value.try_fold_with(&mut folder)?; + let obligations = stalled_goals + .into_iter() + .map(|goal| Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate)) + .collect(); + Ok(Normalized { value, obligations }) } struct ReplaceAliasWithInfer<'me, 'tcx> { @@ -134,6 +143,8 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { if ty.has_escaping_bound_vars() { let (replaced, ..) = BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, alias); + // Keep the higher-ranked alias in the folded value; the fresh term is only + // used to register its projection obligation. let _ = self.term_to_infer(replaced.into()); ty } else { @@ -158,6 +169,8 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { &mut self.universes, alias_const, ); + // Keep the higher-ranked alias in the folded value; the fresh term is only + // used to register its projection obligation. let _ = self.term_to_infer(replaced.into()); ct } else { @@ -222,7 +235,10 @@ where T: TypeFoldable>, E: FromSolverError<'tcx, NextSolverError<'tcx>>, { - let Normalized { value, obligations } = normalize_with_universes(at, value, universes); + let Normalized { value, obligations } = normalize_with_universes(at, value, universes) + .map_err(|obligation| { + thin_vec![E::from_solver_error(at.infcx, NextSolverError::TrueError(obligation))] + })?; let mut fulfill_cx = FulfillmentCtxt::new(at.infcx); for pred in obligations { diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index de65820cf9a75..a64cbb5785a03 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -703,27 +703,5 @@ pub mod __alloc_error_handler { } } -/// Allocator marker trait that is implemented only on `Global`, except when -/// the allocator feature gate is enabled (in which case it is implemented -/// for all allocators). -/// -/// This is to prevent stable code from e.g. constructing `Arc` -/// using the `From> for Arc` impl. -/// -/// Note that this trait cannot appear in specialization impls (even if not -/// specialized on). -/// -/// This trait should be used as a bound whenever a function constructing -/// a type with an `#[unstable] A: Allocator = Global` parameter may be -/// callable for `A != Global`. -#[marker] -#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] -#[doc(hidden)] -pub trait AllocatorNightly: Allocator {} - -#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] -#[unstable_feature_bound(allocator_ext)] -impl AllocatorNightly for A {} - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] impl AllocatorNightly for Global {} diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7504763120532..36af491af1bab 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -206,7 +206,7 @@ use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -use crate::alloc::{AllocError, Allocator, Global, Layout, StaticAllocator}; +use crate::alloc::{AllocError, Allocator, AllocatorNightly, Global, Layout, StaticAllocator}; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked_in; @@ -2541,6 +2541,9 @@ unsafe impl Allocator for Box { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Box {} #[unstable(feature = "random", issue = "130703")] impl core::random::Rng for Box { diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index e61ea5193eccb..41e787ace9765 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -23,9 +23,11 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::sync::atomic::{self, Atomic}; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] -use crate::alloc::{AllocatorNightly, handle_alloc_error}; +use crate::alloc::handle_alloc_error; +use crate::alloc::{ + AllocError, Allocator, AllocatorClone, AllocatorNightly, Global, Layout, StaticAllocator, +}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::is_dangling; @@ -5199,6 +5201,9 @@ unsafe impl Allocator for Arc { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Arc {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Arc {} diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 04e08c47fb587..2608f2c29877f 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -266,9 +266,11 @@ use core::ptr::{self, NonNull, drop_in_place}; use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] -use crate::alloc::{AllocatorNightly, handle_alloc_error}; +use crate::alloc::handle_alloc_error; +use crate::alloc::{ + AllocError, Allocator, AllocatorClone, AllocatorNightly, Global, Layout, StaticAllocator, +}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; #[cfg(not(no_global_oom_handling))] @@ -4837,6 +4839,9 @@ unsafe impl Allocator for Rc { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Rc {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Rc {} diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 11b9da3032ae7..9f671b739cb14 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -743,6 +743,13 @@ where } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl

AllocatorNightly for core::pin::Pin

where + P: core::ops::Deref + core::pin::PinSafePointer +{ +} + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for &A {} @@ -753,3 +760,22 @@ unsafe impl StaticAllocator for &A {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl StaticAllocator for &mut A {} + +/// Allocator marker trait that is only implemented stably for `Global`. +/// +/// This trait is used as a bound whenever a function constructing +/// a type with an `#[unstable] A: Allocator = Global` parameter +/// may be callable for `A != Global`. +/// +/// This is to prevent stable code from e.g. constructing `Arc` +/// using the `From> for Arc` impl. +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +pub trait AllocatorNightly: Allocator {} + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for &A {} + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for &mut A {} diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c6f94944006c9..fdca3d12ba3d4 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -504,3 +504,7 @@ pub mod __default_lib_allocator { } } } + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for System {} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f779fce47cd2f..b97bd93181f7a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -21,7 +21,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_metadata::creader::CStore; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_span::symbol::kw; -use rustc_span::{Ident, Symbol}; +use rustc_span::{Ident, Symbol, sym}; use tracing::{debug, trace}; use super::url_parts_builder::UrlPartsBuilder; @@ -537,11 +537,25 @@ fn generate_item_def_id_path( && !def_id.is_local() && def_id.krate != original_def_id.krate; } else { + // This hack is because primitive types are only documented in `core` and `std`. + // However, with `#[rustc_allow_incoherent_impl]`, a lot of primitive methods are + // implemented in `core`. Some of them are documented in `core` (like `[]::sort`) while + // others aren't (like `[]::to_vec`). So in case we're not documenting `core`, we link + // to `std`. + if !of_trait && crate_name != sym::core { + if ![sym::alloc, sym::std].contains(&crate_name) { + // We cannot link to this primitive's associated item as it's not part of + // `core`, `alloc` or `std` so returning early. + return Err(HrefError::UnnamableItem); + } + maybe_have_impl_not_in_def_crate = true; + } prim = PrimitiveType::from_ty(ty); } } let (shortty, fqp) = if let Some(prim) = prim { + let crate_name = if maybe_have_impl_not_in_def_crate { sym::std } else { crate_name }; (ItemType::Primitive, vec![crate_name, prim.as_sym()]) } else { ( diff --git a/tests/mir-opt/const_prop/maybe_uninit.rs b/tests/mir-opt/const_prop/maybe_uninit.rs index 649fea6252216..89c395a7be5bb 100644 --- a/tests/mir-opt/const_prop/maybe_uninit.rs +++ b/tests/mir-opt/const_prop/maybe_uninit.rs @@ -8,3 +8,10 @@ pub fn u8_array() -> [MaybeUninit; 8] { // CHECK: _0 = const ; [MaybeUninit::uninit(); 8] } + +// EMIT_MIR maybe_uninit.u8_array_assume_init.GVN.diff +pub fn u8_array_assume_init() -> [MaybeUninit; 8] { + // CHECK: fn u8_array_assume_init( + // CHECK: _0 = const ; + unsafe { MaybeUninit::uninit().assume_init() } +} diff --git a/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff new file mode 100644 index 0000000000000..e0c4af329fadc --- /dev/null +++ b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff @@ -0,0 +1,36 @@ +- // MIR for `u8_array_assume_init` before GVN ++ // MIR for `u8_array_assume_init` after GVN + + fn u8_array_assume_init() -> [MaybeUninit; 8] { + let mut _0: [std::mem::MaybeUninit; 8]; + let mut _1: std::mem::MaybeUninit<[std::mem::MaybeUninit; 8]>; + scope 1 (inlined MaybeUninit::<[MaybeUninit; 8]>::uninit) { + } + scope 2 (inlined #[track_caller] MaybeUninit::<[MaybeUninit; 8]>::assume_init) { + scope 3 (inlined transmute_neo::; 8]>, [MaybeUninit; 8]>) { + } + } + + bb0: { + StorageLive(_1); +- _1 = MaybeUninit::<[MaybeUninit; 8]> { uninit: const () }; ++ _1 = const ; + goto -> bb1; + } + + bb1: { +- _0 = copy _1 as [std::mem::MaybeUninit; 8] (Transmute); ++ _0 = const ; + StorageDead(_1); + return; + } ++ } ++ ++ ALLOC0 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs new file mode 100644 index 0000000000000..98e9a5129417c --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs @@ -0,0 +1,7 @@ +#![feature(rustc_attrs)] +#![allow(internal_features)] + +impl [T] { + #[rustc_allow_incoherent_impl] + pub fn f(&self) {} +} diff --git a/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs b/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs new file mode 100644 index 0000000000000..9a4609953a178 --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs @@ -0,0 +1,25 @@ +// This test checks that outside of `core`/`alloc`/`std`, we don't link to incoherent method impl +// because there is no page to link to since primitive are only documented in `core` and `std`. + +//@ aux-build: incoherent_impl_primitive.rs +//@ build-aux-docs +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +extern crate incoherent_impl_primitive; + +//@ has 'src/foo/incoherent_impl-primitive.rs.html' + +// It should contain only the link to "first". Sadly, because of the limit, we cannot test +// if a link doesn't have an attribute so for now, we simply ensure that the number of `` +// (including both line numbers and jump to def links) is superior by one to the number of +// line ``. If so, we know there is only one jump to def link. +//@ count - '//pre/code/a' 7 +//@ count - '//pre/code/a[@id]' 6 +//@ has - '//pre/code/a[@href="{{channel}}/core/primitive.slice.html#method.first"]' 'first' + +fn foo() { + let x = ["a"].f(); + ["a"].first(); +} diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.current.stderr similarity index 88% rename from tests/ui/associated-inherent-types/issue-111404-1.stderr rename to tests/ui/associated-inherent-types/issue-111404-1.current.stderr index 9a5b69497c0cf..b77b3c00a69f9 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-111404-1.rs:10:11 + --> $DIR/issue-111404-1.rs:14:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other @@ -8,7 +8,7 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} found struct `Foo fn(&'b ())>` error[E0308]: mismatched types - --> $DIR/issue-111404-1.rs:10:11 + --> $DIR/issue-111404-1.rs:14:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other @@ -18,13 +18,13 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 + --> $DIR/issue-111404-1.rs:14:1 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 + --> $DIR/issue-111404-1.rs:14:1 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:8 + --> $DIR/issue-111404-1.rs:14:8 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^ diff --git a/tests/ui/associated-inherent-types/issue-111404-1.next.stderr b/tests/ui/associated-inherent-types/issue-111404-1.next.stderr new file mode 100644 index 0000000000000..812a6ee052d29 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111404-1.next.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `Foo::Assoc == &()` + --> $DIR/issue-111404-1.rs:14:11 + | +LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index cad6d48b1c5af..a23856d0eac8d 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ [next] compile-flags: -Znext-solver + #![feature(inherent_associated_types)] #![allow(incomplete_features)] @@ -8,10 +12,11 @@ impl<'a> Foo { } fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} -//~^ ERROR mismatched types [E0308] -//~| ERROR mismatched types [E0308] -//~| ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error +//[current]~^ ERROR mismatched types [E0308] +//[current]~| ERROR mismatched types [E0308] +//[current]~| ERROR higher-ranked subtype error +//[current]~| ERROR higher-ranked subtype error +//[current]~| ERROR higher-ranked subtype error +//[next]~^^^^^^ ERROR type mismatch resolving fn main() {} diff --git a/tests/ui/checked-type-alias/variance-1.stderr b/tests/ui/checked-type-alias/variance-1.stderr index 5eb2f5d0673aa..40b59b43910e8 100644 --- a/tests/ui/checked-type-alias/variance-1.stderr +++ b/tests/ui/checked-type-alias/variance-1.stderr @@ -10,7 +10,7 @@ error[E0392]: type parameter `T` is never used --> $DIR/variance-1.rs:17:24 | LL | struct WrapDiscard<'a, T>(Discard<'a, T>); - | ^ - `T` is named here, but is likely unused in the containing type + | ^ - `T` is named here, but is not used in the type that wraps it | | | unused type parameter | diff --git a/tests/ui/checked-type-alias/variance-overflow.rs b/tests/ui/checked-type-alias/variance-overflow.rs index 0b5b58e083133..3da7da1ed425d 100644 --- a/tests/ui/checked-type-alias/variance-overflow.rs +++ b/tests/ui/checked-type-alias/variance-overflow.rs @@ -19,4 +19,15 @@ struct First(Second); type Second = Second; // diverging free alias type //~^ ERROR overflow normalizing the type alias `Second` +// The same applies when a diverging alias mentions a type parameter. The argument grows with +// every step, so there is no repeated `(DefId, args)` pair to detect the divergence with. +// Variance inference must stop at the recursion limit, and reporting the unused parameter +// must not restart the expansion. +type Diverging = Diverging<(T,)>; +//~^ ERROR overflow normalizing the type alias `Diverging< + +struct Wrap(Diverging); +//~^ ERROR type parameter `T` is never used +//~| ERROR overflow normalizing the type alias `Diverging< + fn main() {} diff --git a/tests/ui/checked-type-alias/variance-overflow.stderr b/tests/ui/checked-type-alias/variance-overflow.stderr index 35486ccdc169f..3ea61d9ade9f3 100644 --- a/tests/ui/checked-type-alias/variance-overflow.stderr +++ b/tests/ui/checked-type-alias/variance-overflow.stderr @@ -23,7 +23,34 @@ LL | type Second = Second; // diverging free alias type | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error: aborting due to 3 previous errors +error[E0275]: overflow normalizing the type alias `Diverging<(((((((_,),),),),),),)>` + --> $DIR/variance-overflow.rs:26:1 + | +LL | type Diverging = Diverging<(T,)>; + | ^^^^^^^^^^^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-overflow.rs:29:13 + | +LL | struct Wrap(Diverging); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0275]: overflow normalizing the type alias `Diverging<(((((((_,),),),),),),)>` + --> $DIR/variance-overflow.rs:29:16 + | +LL | struct Wrap(Diverging); + | ^^^^^^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0275, E0392. For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs new file mode 100644 index 0000000000000..22542e4142fb5 --- /dev/null +++ b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs @@ -0,0 +1,25 @@ +// A mention forwarded through free aliases still does not count as a use when the final type +// ignores the parameter. The diagnostic should label the original mention even though the +// intermediate aliases mention the parameter too. + +#![feature(checked_type_aliases)] + +struct Ignores {} +//~^ ERROR type parameter `T` is never used + +type Forward = Discard; +type Discard = Ignores; + +struct Wrap(Forward); +//~^ ERROR type parameter `T` is never used + +// An alias can occur with different arguments in the same type. Here `Repeat` preserves its +// parameter through `Id`, so the enclosing struct uses `T` only recursively. The unrelated +// `Id` must not hide that recursive use. +type Id = T; +type Repeat = (Id, Id); + +struct Recursive(Repeat>>); +//~^ ERROR type parameter `T` is only used recursively + +fn main() {} diff --git a/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr new file mode 100644 index 0000000000000..069916d57b514 --- /dev/null +++ b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr @@ -0,0 +1,34 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-param-through-alias-chain.rs:7:16 + | +LL | struct Ignores {} + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-param-through-alias-chain.rs:13:13 + | +LL | struct Wrap(Forward); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: type parameter `T` is only used recursively + --> $DIR/variance-unused-param-through-alias-chain.rs:22:42 + | +LL | struct Recursive(Repeat>>); + | - ^ + | | + | type parameter must be used non-recursively in the definition + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = note: all type parameters must be used in a non-recursive way in order to constrain their variance + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr new file mode 100644 index 0000000000000..e8fb5732febdc --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr new file mode 100644 index 0000000000000..017884aff53a4 --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr @@ -0,0 +1,54 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr new file mode 100644 index 0000000000000..e8fb5732febdc --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr new file mode 100644 index 0000000000000..017884aff53a4 --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr @@ -0,0 +1,54 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs new file mode 100644 index 0000000000000..72bed90bba4c7 --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs @@ -0,0 +1,17 @@ +//! Test that span parents (which are incremental only) are ignored when deduplicating diagnostics. +//! Regression test for #162901. + +//@ revisions: dedup dup incr-dedup incr-dup +//@[dedup] compile-flags: -Z deduplicate-diagnostics=yes +//@[incr-dup] incremental +//@[incr-dedup] incremental +//@[incr-dedup] compile-flags: -Z deduplicate-diagnostics=yes + +#[global_allocator] +static A: usize = 0; +//[dedup,dup,incr-dedup,incr-dup]~^ ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 + +fn main() {} diff --git a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs index 17a81b5705dfb..6acc1baf319ef 100644 --- a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs +++ b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs @@ -11,8 +11,6 @@ impl<'a> Foo { } fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} -//~^ ERROR: higher-ranked subtype error -//~| ERROR: lifetime bound not satisfied [E0478] -//~| ERROR: lifetime bound not satisfied [E0478] +//~^ ERROR type mismatch resolving fn main() {} diff --git a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr index 47227014ec567..4a032c267e80a 100644 --- a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr +++ b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr @@ -1,23 +1,9 @@ -error[E0478]: lifetime bound not satisfied +error[E0271]: type mismatch resolving `Foo::Assoc == &()` --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0478]: lifetime bound not satisfied - --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:11 - | -LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: higher-ranked subtype error - --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:8 - | -LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0478`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs new file mode 100644 index 0000000000000..de94cad403a3a --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs @@ -0,0 +1,34 @@ +//@ needs-rustc-debug-assertions +//@ compile-flags: -Znext-solver + +// Regression test for #160875. +// +// Eagerly normalizing the inner alias makes the outer alias fail the leak check: +// `Foo fn(&'b ())>` cannot be equated with the impl's `Foo`. +// Deep normalization must propagate that failure. Retrying the original aliases +// with `ReplaceAliasWithInfer` instead moved the lifetime equalities into nested +// goals, whose constraints were invisible to the parent's leak check. +// +// The fallback incorrectly succeeded and returned `fn(?3t)`. Resolving that value +// only hid the failed leak check. With debug assertions enabled, returning the +// unresolved value also triggered an assertion in `normalize_erasing_regions`. +// +// The invalid const body reaches MIR signature normalization in metadata-only +// tests. Keep debug assertions enabled to catch the original ICE as well. + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo(T); + +impl<'a> Foo { + type Assoc = &'a (); +} + +const fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) { + //~^ ERROR type mismatch resolving + x + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr new file mode 100644 index 0000000000000..680e5f702b423 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/deeply-normalize-fallback-issue-160875.rs:30:5 + | +LL | x + | ^ not found in this scope + +error[E0271]: type mismatch resolving `Foo::Assoc == &()` + --> $DIR/deeply-normalize-fallback-issue-160875.rs:28:17 + | +LL | const fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0425. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs index ef3c41ca5560c..bad994b5e280d 100644 --- a/tests/ui/variance/variance-unused-type-param.rs +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -33,4 +33,29 @@ struct DoubleNothing { s: SomeStruct, } +// A mention nested inside another type argument still does not count as a use. +struct NestedNothing { +//~^ ERROR parameter `T` is never used + s: SomeStruct>, +} + +type Discard = (); +//~^ ERROR parameter `T` is never used + +struct ThroughTypeAlias(Discard); +//~^ ERROR parameter `T` is never used + +// Only the unused parameter should receive the diagnostic. +struct SecondUnused { a: A } +//~^ ERROR parameter `B` is never used + +struct UsesSecondUnused(SecondUnused); +//~^ ERROR parameter `T` is never used + +// The alias mentions `T`, but only to forward it to something that throws it away. +type Forward = SomeStruct; + +struct ThroughForwardingAlias(Forward); +//~^ ERROR parameter `T` is never used + fn main() {} diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index c747532e62836..d02addc5a5e53 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -69,11 +69,75 @@ LL | struct DoubleNothing { | ^ unused type parameter LL | LL | s: SomeStruct, - | - `T` is named here, but is likely unused in the containing type + | - `T` is named here, but is not used in the type that wraps it | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error: aborting due to 8 previous errors +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:37:22 + | +LL | struct NestedNothing { + | ^ unused type parameter +LL | +LL | s: SomeStruct>, + | - `T` is named here, but is not used in the type that wraps it + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0091]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:42:14 + | +LL | type Discard = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:45:25 + | +LL | struct ThroughTypeAlias(Discard); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `B` is never used + --> $DIR/variance-unused-type-param.rs:49:24 + | +LL | struct SecondUnused { a: A } + | ^ unused type parameter + | + = help: consider removing `B`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `B` to be a const parameter, use `const B: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:52:25 + | +LL | struct UsesSecondUnused(SecondUnused); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:58:31 + | +LL | struct ThroughForwardingAlias(Forward); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0392`. +Some errors have detailed explanations: E0091, E0392. +For more information about an error, try `rustc --explain E0091`. diff --git a/typos.toml b/typos.toml index 8976759b3b259..215a971527e85 100644 --- a/typos.toml +++ b/typos.toml @@ -35,6 +35,7 @@ numer = "numer" # short for numerator, not a typo for "number" old-skool = "old-skool" # variant spelling of "old-school" optin = "optin" # short for opt-in publically = "publically" +raison = "raison" # part of the French phrase "raison d'être" rplace = "rplace" # short for R-place splitted = "splitted" sythetic = "sythetic" # typo in vendored LLVM sources