diff --git a/Cargo.lock b/Cargo.lock index ee6726eae514d..6e95fd66267d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3699,6 +3699,9 @@ dependencies = [ [[package]] name = "rustc_fs_util" version = "0.0.0" +dependencies = [ + "tempfile", +] [[package]] name = "rustc_graphviz" @@ -4011,7 +4014,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "tempfile", "tracing", ] diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 34c84c64070d2..1e1bdfb5977af 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -13,9 +13,9 @@ use object::read::archive::ArchiveFile; use object::read::macho::FatArch; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; +use rustc_fs_util::TempDirBuilder; use rustc_session::Session; use rustc_span::Symbol; -use tempfile::Builder as TempFileBuilder; use tracing::trace; use super::metadata::search_for_section; @@ -501,7 +501,7 @@ impl<'a> ArArchiveBuilder<'a> { // it creates. We need it to be the default mode for back compat reasons however. (See // #107495) To handle this we are telling tempfile to create a temporary directory instead // and then inside this directory create a file using File::create. - let archive_tmpdir = TempFileBuilder::new() + let archive_tmpdir = TempDirBuilder::new() .suffix(".temp-archive") .tempdir_in(output.parent().unwrap_or_else(|| Path::new(""))) .map_err(|err| { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f0c47ac41e8a0..323538969d73b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; -use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; +use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_macros::LintDiagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; @@ -48,7 +48,6 @@ use rustc_target::spec::{ LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, }; -use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -100,7 +99,7 @@ pub fn link_binary( }); if outputs.outputs.should_link() { - let tmpdir = TempFileBuilder::new() + let tmpdir = TempDirBuilder::new() .prefix("rustc") .tempdir() .unwrap_or_else(|error| sess.dcx().emit_fatal(errors::CreateTempDir { error })); diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index baca3bc7d49eb..90a6acade8b03 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -5,4 +5,5 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +tempfile = "3.7.1" # tidy-alphabetical-end diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 0df1b243d697e..7a883a13b72da 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -1,6 +1,8 @@ -use std::ffi::CString; +use std::ffi::{CString, OsStr}; use std::path::{Path, PathBuf, absolute}; -use std::{fs, io}; +use std::{env, fs, io}; + +use tempfile::TempDir; // Unfortunately, on windows, it looks like msvcrt.dll is silently translating // verbatim paths under the hood to non-verbatim paths! This manifests itself as @@ -102,3 +104,43 @@ pub fn path_to_c_string(p: &Path) -> CString { pub fn try_canonicalize>(path: P) -> io::Result { fs::canonicalize(&path).or_else(|_| absolute(&path)) } + +pub struct TempDirBuilder<'a, 'b> { + builder: tempfile::Builder<'a, 'b>, +} + +impl<'a, 'b> TempDirBuilder<'a, 'b> { + pub fn new() -> Self { + Self { builder: tempfile::Builder::new() } + } + + pub fn prefix + ?Sized>(&mut self, prefix: &'a S) -> &mut Self { + self.builder.prefix(prefix); + self + } + + pub fn suffix + ?Sized>(&mut self, suffix: &'b S) -> &mut Self { + self.builder.suffix(suffix); + self + } + + pub fn tempdir_in>(&self, dir: P) -> io::Result { + let dir = dir.as_ref(); + // On Windows in CI, we had been getting fairly frequent "Access is denied" + // errors when creating temporary directories. + // So this implements a simple retry with backoff loop. + #[cfg(windows)] + for wait in 1..11 { + match self.builder.tempdir_in(dir) { + Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {} + t => return t, + } + std::thread::sleep(std::time::Duration::from_millis(1 << wait)); + } + self.builder.tempdir_in(dir) + } + + pub fn tempdir(&self) -> io::Result { + self.tempdir_in(env::temp_dir()) + } +} diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 68058250a2671..ed5edeef1617d 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -229,6 +229,7 @@ pub fn initialize_available_targets() { LLVMInitializeXtensaTargetInfo, LLVMInitializeXtensaTarget, LLVMInitializeXtensaTargetMC, + LLVMInitializeXtensaAsmPrinter, LLVMInitializeXtensaAsmParser ); init_target!( diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 08dcc3d519a2b..b11f9260be7c0 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -26,7 +26,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -tempfile = "3.2" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index c4e1e0f1d1a99..e57534b847ef0 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -2,11 +2,11 @@ use std::path::{Path, PathBuf}; use std::{fs, io}; use rustc_data_structures::temp_dir::MaybeTempDir; +use rustc_fs_util::TempDirBuilder; use rustc_middle::ty::TyCtxt; use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; use rustc_session::{MetadataKind, Session}; -use tempfile::Builder as TempFileBuilder; use crate::errors::{ BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile, @@ -45,7 +45,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { // final destination, with an `fs::rename` call. In order for the rename to // always succeed, the temporary file needs to be on the same filesystem, // which is why we create it inside the output directory specifically. - let metadata_tmpdir = TempFileBuilder::new() + let metadata_tmpdir = TempDirBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err })); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 98057a25f04c7..e8dad1e056cbd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -590,6 +590,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.defaultness(def_id).has_value() } + fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool { + self.specializes((impl_def_id, victim_def_id)) + } + fn impl_is_default(self, impl_def_id: DefId) -> bool { self.defaultness(impl_def_id).is_default() } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index ecb57cc0ad71b..381a732b8dee9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -10,6 +10,7 @@ use rustc_type_ir::{ }; use tracing::{debug, instrument}; +use super::has_only_region_constraints; use super::trait_goals::TraitGoalProvenVia; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; @@ -771,6 +772,69 @@ where } }) } +} + +pub(super) enum AllowInferenceConstraints { + Yes, + No, +} + +impl EvalCtxt<'_, D> +where + D: SolverDelegate, + I: Interner, +{ + /// Check whether we can ignore impl candidates due to specialization. + /// + /// This is only necessary for `feature(specialization)` and seems quite ugly. + pub(super) fn filter_specialized_impls( + &mut self, + allow_inference_constraints: AllowInferenceConstraints, + candidates: &mut Vec>, + ) { + match self.typing_mode() { + TypingMode::Coherence => return, + TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => {} + } + + let mut i = 0; + 'outer: while i < candidates.len() { + let CandidateSource::Impl(victim_def_id) = candidates[i].source else { + i += 1; + continue; + }; + + for (j, c) in candidates.iter().enumerate() { + if i == j { + continue; + } + + let CandidateSource::Impl(other_def_id) = c.source else { + continue; + }; + + // See if we can toss out `victim` based on specialization. + // + // While this requires us to know *for sure* that the `lhs` impl applies + // we still use modulo regions here. This is fine as specialization currently + // assumes that specializing impls have to be always applicable, meaning that + // the only allowed region constraints may be constraints also present on the default impl. + if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes) + || has_only_region_constraints(c.result) + { + if self.cx().impl_specializes(other_def_id, victim_def_id) { + candidates.remove(i); + continue 'outer; + } + } + } + + i += 1; + } + } /// Assemble and merge candidates for goals which are related to an underlying trait /// goal. Right now, this is normalizes-to and host effect goals. @@ -857,7 +921,7 @@ where } } TraitGoalProvenVia::Misc => { - let candidates = + let mut candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); // Prefer "orphaned" param-env normalization predicates, which are used @@ -871,6 +935,13 @@ where return Ok(response); } + // We drop specialized impls to allow normalization via a final impl here. In case + // the specializing impl has different inference constraints from the specialized + // impl, proving the trait goal is already ambiguous, so we never get here. This + // means we can just ignore inference constraints and don't have to special-case + // constraining the normalized-to `term`. + self.filter_specialized_impls(AllowInferenceConstraints::Yes, &mut candidates); + let responses: Vec<_> = candidates.iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&responses) { Ok(response) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 27ca8787db5c5..19fb2b00fcb3a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -16,6 +16,7 @@ use rustc_type_ir::{ }; use tracing::{instrument, trace}; +use super::has_only_region_constraints; use crate::coherence; use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; @@ -476,13 +477,8 @@ where Ok(response) => response, }; - let has_changed = if !response.value.var_values.is_identity_modulo_regions() - || !response.value.external_constraints.opaque_types.is_empty() - { - HasChanged::Yes - } else { - HasChanged::No - }; + let has_changed = + if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 0695c5acdcab3..d9cf84787a036 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -70,6 +70,17 @@ fn has_no_inference_or_external_constraints( && normalization_nested_goals.is_empty() } +fn has_only_region_constraints(response: ty::Canonical>) -> bool { + let ExternalConstraintsData { + region_constraints: _, + ref opaque_types, + ref normalization_nested_goals, + } = *response.value.external_constraints; + response.value.var_values.is_identity_modulo_regions() + && opaque_types.is_empty() + && normalization_nested_goals.is_empty() +} + impl<'a, D, I> EvalCtxt<'a, D> where D: SolverDelegate, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 9466901683e21..119d197de134f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -213,9 +213,6 @@ where ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; - // In case the associated item is hidden due to specialization, we have to - // return ambiguity this would otherwise be incomplete, resulting in - // unsoundness during coherence (#105782). let target_item_def_id = match ecx.fetch_eligible_assoc_item( goal_trait_ref, goal.predicate.def_id(), @@ -223,8 +220,28 @@ where ) { Ok(Some(target_item_def_id)) => target_item_def_id, Ok(None) => { - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + match ecx.typing_mode() { + // In case the associated item is hidden due to specialization, we have to + // return ambiguity this would otherwise be incomplete, resulting in + // unsoundness during coherence (#105782). + ty::TypingMode::Coherence => { + return ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ); + } + // Outside of coherence, we treat the associated item as rigid instead. + ty::TypingMode::Analysis { .. } + | ty::TypingMode::Borrowck { .. } + | ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::PostAnalysis => { + ecx.structurally_instantiate_normalizes_to_term( + goal, + goal.predicate.alias, + ); + return ecx + .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + } + }; } Err(guar) => return error_response(ecx, guar), }; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 3404c47bba2a3..24657496df6a5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -13,7 +13,7 @@ use tracing::{instrument, trace}; use crate::delegate::SolverDelegate; use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; -use crate::solve::assembly::{self, AssembleCandidatesFrom, Candidate}; +use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate}; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, @@ -1338,6 +1338,8 @@ where }; } + self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates); + // If there are *only* global where bounds, then make sure to return that this // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index ae9143486eea3..ac4f7ed64e22f 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -675,6 +675,8 @@ parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns ar parse_nul_in_c_str = null characters in C string literals are not supported +parse_or_in_let_chain = `||` operators are not supported in let chain conditions + parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings parse_out_of_range_hex_escape = out of range hex escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 35cf4c1b00d4b..6a6fb0eb9b5ba 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -478,6 +478,13 @@ pub(crate) struct ExpectedExpressionFoundLet { pub comparison: Option, } +#[derive(Diagnostic)] +#[diag(parse_or_in_let_chain)] +pub(crate) struct OrInLetChain { + #[primary_span] + pub span: Span, +} + #[derive(Subdiagnostic, Clone, Copy)] #[multipart_suggestion( parse_maybe_missing_let, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 370eb3f402d93..f3b53971b2957 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4073,14 +4073,18 @@ impl MutVisitor for CondChecker<'_> { match e.kind { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { - *recovered = Recovered::Yes(self.parser.dcx().emit_err( - errors::ExpectedExpressionFoundLet { + let error = match reason { + NotSupportedOr(or_span) => { + self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span }) + } + _ => self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet { span, reason, missing_let: self.missing_let, comparison: self.comparison, - }, - )); + }), + }; + *recovered = Recovered::Yes(error); } else if self.depth > 1 { // Top level `let` is always allowed; only gate chains match self.let_chains_policy { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 848d0646d009f..1f4fa5aac102a 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -163,15 +163,15 @@ where fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); let mut errors = Vec::new(); - for i in 0.. { - if !infcx.tcx.recursion_limit().value_within_limit(i) { - self.obligations.on_fulfillment_overflow(infcx); - // Only return true errors that we have accumulated while processing. - return errors; - } - + loop { let mut has_changed = false; - for obligation in self.obligations.drain_pending(|_| true) { + for mut obligation in self.obligations.drain_pending(|_| true) { + if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { + self.obligations.on_fulfillment_overflow(infcx); + // Only return true errors that we have accumulated while processing. + return errors; + } + let goal = obligation.as_goal(); let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span) @@ -189,6 +189,13 @@ where }; if changed == HasChanged::Yes { + // We increment the recursion depth here to track the number of times + // this goal has resulted in inference progress. This doesn't precisely + // model the way that we track recursion depth in the old solver due + // to the fact that we only process root obligations, but it is a good + // approximation and should only result in fulfillment overflow in + // pathological cases. + obligation.recursion_depth += 1; has_changed = true; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index ab38556589e03..9758cecaf6ac7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -286,6 +286,8 @@ pub trait Interner: fn has_item_definition(self, def_id: Self::DefId) -> bool; + fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool; + fn impl_is_default(self, impl_def_id: Self::DefId) -> bool; fn impl_trait_ref(self, impl_def_id: Self::DefId) -> ty::EarlyBinder>; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index c46dcebedcab8..36a1c57b02012 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -513,13 +513,13 @@ impl Span { } /// Creates an empty span pointing to directly before this span. - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_span_location", since = "CURRENT_RUSTC_VERSION")] pub fn start(&self) -> Span { Span(self.0.start()) } /// Creates an empty span pointing to directly after this span. - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_span_location", since = "CURRENT_RUSTC_VERSION")] pub fn end(&self) -> Span { Span(self.0.end()) } @@ -527,7 +527,7 @@ impl Span { /// The one-indexed line of the source file where the span starts. /// /// To obtain the line of the span's end, use `span.end().line()`. - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_span_location", since = "CURRENT_RUSTC_VERSION")] pub fn line(&self) -> usize { self.0.line() } @@ -535,7 +535,7 @@ impl Span { /// The one-indexed column of the source file where the span starts. /// /// To obtain the column of the span's end, use `span.end().column()`. - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_span_location", since = "CURRENT_RUSTC_VERSION")] pub fn column(&self) -> usize { self.0.column() } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 91701576130e6..c9595b051e207 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -388,11 +388,15 @@ mod enum_keyword {} /// lazy_static;`. The other use is in foreign function interfaces (FFI). /// /// `extern` is used in two different contexts within FFI. The first is in the form of external -/// blocks, for declaring function interfaces that Rust code can call foreign code by. +/// blocks, for declaring function interfaces that Rust code can call foreign code by. This use +/// of `extern` is unsafe, since we are asserting to the compiler that all function declarations +/// are correct. If they are not, using these items may lead to undefined behavior. /// /// ```rust ignore +/// // SAFETY: The function declarations given below are in +/// // line with the header files of `my_c_library`. /// #[link(name = "my_c_library")] -/// extern "C" { +/// unsafe extern "C" { /// fn my_c_function(x: i32) -> bool; /// } /// ``` diff --git a/tests/ui/coroutine/dont-drop-stalled-generators.rs b/tests/ui/coroutine/dont-drop-stalled-generators.rs new file mode 100644 index 0000000000000..8e0c45a9773b3 --- /dev/null +++ b/tests/ui/coroutine/dont-drop-stalled-generators.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass +//@ edition: 2024 + +// This test previously used the `is_copy_raw` query during +// HIR typeck, dropping the list of generators from the current +// body. This then caused a query cycle. + +struct W(*const T); + +impl Clone for W { + fn clone(&self) -> Self { W(self.0) } +} + +impl Copy for W {} + +fn main() { + let coro = async {}; + let x = W(&raw const coro); + let c = || { + let x = x; + }; +} diff --git a/tests/ui/parser/or-in-let-chain.edition2021.stderr b/tests/ui/parser/or-in-let-chain.edition2021.stderr new file mode 100644 index 0000000000000..a97095cc3b82e --- /dev/null +++ b/tests/ui/parser/or-in-let-chain.edition2021.stderr @@ -0,0 +1,28 @@ +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:6:24 + | +LL | if let true = true || false {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/or-in-let-chain.rs:9:9 + | +LL | if (let true = true) || false {} + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:12:24 + | +LL | if let true = true || false || true {} + | ^^ + +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:15:33 + | +LL | if let true = true && false || true {} + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/or-in-let-chain.edition2024.stderr b/tests/ui/parser/or-in-let-chain.edition2024.stderr new file mode 100644 index 0000000000000..a97095cc3b82e --- /dev/null +++ b/tests/ui/parser/or-in-let-chain.edition2024.stderr @@ -0,0 +1,28 @@ +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:6:24 + | +LL | if let true = true || false {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/or-in-let-chain.rs:9:9 + | +LL | if (let true = true) || false {} + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:12:24 + | +LL | if let true = true || false || true {} + | ^^ + +error: `||` operators are not supported in let chain conditions + --> $DIR/or-in-let-chain.rs:15:33 + | +LL | if let true = true && false || true {} + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/or-in-let-chain.rs b/tests/ui/parser/or-in-let-chain.rs new file mode 100644 index 0000000000000..4c4372bb00f0f --- /dev/null +++ b/tests/ui/parser/or-in-let-chain.rs @@ -0,0 +1,17 @@ +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] edition: 2024 + +fn main() { + if let true = true || false {} + //~^ ERROR `||` operators are not supported in let chain conditions + // With parentheses + if (let true = true) || false {} + //~^ ERROR expected expression, found `let` statement + // Multiple || operators + if let true = true || false || true {} + //~^ ERROR `||` operators are not supported in let chain conditions + // Mixed operators (should still show error for ||) + if let true = true && false || true {} + //~^ ERROR `||` operators are not supported in let chain conditions +} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs index ae13f7c76badd..ed461af66aaf9 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs @@ -3,7 +3,7 @@ fn let_or_guard(x: Result, ()>) { match x { Ok(opt) if let Some(4) = opt || false => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `||` operators are not supported in let chain conditions _ => {} } } diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr index 4b85fdd505057..0566d96fddc31 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.stderr @@ -1,11 +1,4 @@ -error: expected expression, found `let` statement - --> $DIR/ast-validate-guards.rs:5:20 - | -LL | Ok(opt) if let Some(4) = opt || false => {} - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/ast-validate-guards.rs:5:38 | LL | Ok(opt) if let Some(4) = opt || false => {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index 817e226bc45d5..141a6d255d086 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -272,14 +272,7 @@ LL | if (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:16 - | -LL | if true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} @@ -485,14 +478,7 @@ LL | while (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:19 - | -LL | while true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr index bab50c22c0308..dda09de4c5344 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -272,14 +272,7 @@ LL | if (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:16 - | -LL | if true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} @@ -485,14 +478,7 @@ LL | while (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:19 - | -LL | while true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index 943956feb4e07..5b53691cbf546 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -272,14 +272,7 @@ LL | if (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:16 - | -LL | if true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} @@ -485,14 +478,7 @@ LL | while (let 0 = 0)? {} | = note: only supported directly in conditions of `if` and `while` expressions -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:19 - | -LL | while true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions +error: `||` operators are not supported in let chain conditions --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 0b0abe6ec1754..65beccf2214fd 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -119,7 +119,7 @@ fn nested_within_if_expr() { //~^ ERROR expected expression, found `let` statement if true || let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `||` operators are not supported in let chain conditions if (true || let 0 = 0) {} //~^ ERROR expected expression, found `let` statement if true && (true || let 0 = 0) {} @@ -210,7 +210,7 @@ fn nested_within_while_expr() { //~^ ERROR expected expression, found `let` statement while true || let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `||` operators are not supported in let chain conditions while (true || let 0 = 0) {} //~^ ERROR expected expression, found `let` statement while true && (true || let 0 = 0) {} diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr b/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr new file mode 100644 index 0000000000000..7e3df0c83f9f3 --- /dev/null +++ b/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/prefer-specializing-impl-over-default.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr b/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr new file mode 100644 index 0000000000000..7e3df0c83f9f3 --- /dev/null +++ b/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/prefer-specializing-impl-over-default.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.rs b/tests/ui/specialization/prefer-specializing-impl-over-default.rs new file mode 100644 index 0000000000000..af6837b30cafa --- /dev/null +++ b/tests/ui/specialization/prefer-specializing-impl-over-default.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait WithAssoc: 'static { + type Assoc; +} +impl WithAssoc for (T,) { + type Assoc = (); +} + +struct GenericArray(U::Assoc); + +trait AbiExample { + fn example(); +} +impl AbiExample for GenericArray { + fn example() {} +} +impl AbiExample for T { + default fn example() {} +} + +fn main() { + let _ = GenericArray::<((),)>::example(); +} diff --git a/tests/ui/specialization/specialization-default-projection.stderr b/tests/ui/specialization/specialization-default-projection.current.stderr similarity index 91% rename from tests/ui/specialization/specialization-default-projection.stderr rename to tests/ui/specialization/specialization-default-projection.current.stderr index b8b81876d8131..038c379c43e13 100644 --- a/tests/ui/specialization/specialization-default-projection.stderr +++ b/tests/ui/specialization/specialization-default-projection.current.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-default-projection.rs:1:12 + --> $DIR/specialization-default-projection.rs:5:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/specialization-default-projection.rs:21:5 + --> $DIR/specialization-default-projection.rs:25:5 | LL | fn generic() -> ::Assoc { | ----------------- expected `::Assoc` because of return type @@ -23,7 +23,7 @@ LL | () = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/specialization-default-projection.rs:28:5 + --> $DIR/specialization-default-projection.rs:32:5 | LL | fn monomorphic() -> () { | -- expected `()` because of return type diff --git a/tests/ui/specialization/specialization-default-projection.next.stderr b/tests/ui/specialization/specialization-default-projection.next.stderr new file mode 100644 index 0000000000000..9111f173a9c87 --- /dev/null +++ b/tests/ui/specialization/specialization-default-projection.next.stderr @@ -0,0 +1,43 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-projection.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:25:5 + | +LL | fn generic() -> ::Assoc { + | ----------------- expected `::Assoc` because of return type +... +LL | () + | ^^ types differ + | + = note: expected associated type `::Assoc` + found unit type `()` + = help: consider constraining the associated type `::Assoc` to `()` or calling a method that returns `::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:32:5 + | +LL | fn monomorphic() -> () { + | -- expected `()` because of return type +... +LL | generic::<()>() + | ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | types differ + | + = note: expected unit type `()` + found associated type `<() as Foo>::Assoc` + = help: consider constraining the associated type `<() as Foo>::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-default-projection.rs b/tests/ui/specialization/specialization-default-projection.rs index 7f3ae951287ca..4f69ccb59746b 100644 --- a/tests/ui/specialization/specialization-default-projection.rs +++ b/tests/ui/specialization/specialization-default-projection.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we can't project defaulted associated types diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.current.stderr similarity index 91% rename from tests/ui/specialization/specialization-default-types.stderr rename to tests/ui/specialization/specialization-default-types.current.stderr index 774ac9536175d..67477f9a6d537 100644 --- a/tests/ui/specialization/specialization-default-types.stderr +++ b/tests/ui/specialization/specialization-default-types.current.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-default-types.rs:5:12 + --> $DIR/specialization-default-types.rs:9:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/specialization-default-types.rs:15:9 + --> $DIR/specialization-default-types.rs:19:9 | LL | default type Output = Box; | ----------------------------- associated type is `default` and may be overridden @@ -22,7 +22,7 @@ LL | Box::new(self) found struct `Box` error[E0308]: mismatched types - --> $DIR/specialization-default-types.rs:25:5 + --> $DIR/specialization-default-types.rs:29:5 | LL | fn trouble(t: T) -> Box { | ------ expected `Box` because of return type diff --git a/tests/ui/specialization/specialization-default-types.next.stderr b/tests/ui/specialization/specialization-default-types.next.stderr new file mode 100644 index 0000000000000..4f7c47654460e --- /dev/null +++ b/tests/ui/specialization/specialization-default-types.next.stderr @@ -0,0 +1,39 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-types.rs:9:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:19:9 + | +LL | default type Output = Box; + | ----------------------------- associated type is `default` and may be overridden +LL | default fn generate(self) -> Self::Output { + | ------------ expected `::Output` because of return type +LL | Box::new(self) + | ^^^^^^^^^^^^^^ types differ + | + = note: expected associated type `::Output` + found struct `Box` + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:29:5 + | +LL | fn trouble(t: T) -> Box { + | ------ expected `Box` because of return type +LL | Example::generate(t) + | ^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: expected struct `Box` + found associated type `::Output` + = help: consider constraining the associated type `::Output` to `Box` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-default-types.rs b/tests/ui/specialization/specialization-default-types.rs index 346471f11e4a8..77817abea127c 100644 --- a/tests/ui/specialization/specialization-default-types.rs +++ b/tests/ui/specialization/specialization-default-types.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + // It should not be possible to use the concrete value of a defaulted // associated type in the impl defining it -- otherwise, what happens // if it's overridden? diff --git a/tests/ui/traits/next-solver/coerce-depth.rs b/tests/ui/traits/next-solver/coerce-depth.rs new file mode 100644 index 0000000000000..c8fc3fcab59d8 --- /dev/null +++ b/tests/ui/traits/next-solver/coerce-depth.rs @@ -0,0 +1,31 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Ensure that a stack of coerce predicates doesn't end up overflowing when they get procesed +// in *reverse* order, which may require O(N) iterations of the fulfillment loop. + +#![recursion_limit = "16"] + +fn main() { + match 0 { + 0 => None, + 1 => None, + 2 => None, + 3 => None, + 4 => None, + 5 => None, + 6 => None, + 7 => None, + 8 => None, + 9 => None, + 10 => None, + 11 => None, + 12 => None, + 13 => None, + 14 => None, + 15 => None, + 16 => None, + 17 => None, + _ => Some(1u32), + }; +} diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index 376fa22ae1923..f1447cd6a9e2e 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -10,11 +10,8 @@ trait Default { impl Default for T { default type Id = T; - // This will be fixed by #111994 fn intu(&self) -> &Self::Id { - //~^ ERROR type annotations needed - //~| ERROR cannot normalize `::Id: '_` - self //~ ERROR cannot satisfy + self //~ ERROR mismatched types } } @@ -25,6 +22,7 @@ fn transmute, U: Copy>(t: T) -> U { use std::num::NonZero; fn main() { - let s = transmute::>>(0); //~ ERROR cannot satisfy + let s = transmute::>>(0); + //~^ ERROR type mismatch resolving `::Id == Option>` assert_eq!(s, None); } diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index eeb101911c435..8bd290ea19707 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -8,37 +8,32 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error: cannot normalize `::Id: '_` - --> $DIR/specialization-transmute.rs:14:5 +error[E0308]: mismatched types + --> $DIR/specialization-transmute.rs:14:9 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:14:23 - | -LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot infer type for reference `&::Id` - -error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to T` - --> $DIR/specialization-transmute.rs:17:9 - | + | --------- expected `&::Id` because of return type LL | self - | ^^^^ cannot satisfy `::Id normalizes-to T` + | ^^^^ types differ + | + = note: expected reference `&::Id` + found reference `&T` -error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to Option>` - --> $DIR/specialization-transmute.rs:28:13 +error[E0271]: type mismatch resolving `::Id == Option>` + --> $DIR/specialization-transmute.rs:25:50 | LL | let s = transmute::>>(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `::Id normalizes-to Option>` + | ------------------------------------ ^ types differ + | | + | required by a bound introduced by this call | note: required by a bound in `transmute` - --> $DIR/specialization-transmute.rs:21:25 + --> $DIR/specialization-transmute.rs:18:25 | LL | fn transmute, U: Copy>(t: T) -> U { | ^^^^^^ required by this bound in `transmute` -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs index 2bbe784011071..6835c0764d6c8 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs @@ -18,5 +18,5 @@ fn test, U>() {} fn main() { test::(); - //~^ ERROR cannot satisfy `::Id normalizes-to ()` + //~^ ERROR type mismatch resolving `::Id == ()` } diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr index e1d785b554bd3..1bcf5eddb5bca 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr @@ -8,11 +8,11 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to ()` - --> $DIR/specialization-unconstrained.rs:20:5 +error[E0271]: type mismatch resolving `::Id == ()` + --> $DIR/specialization-unconstrained.rs:20:12 | LL | test::(); - | ^^^^^^^^^^^^^^^^^ cannot satisfy `::Id normalizes-to ()` + | ^^^ types differ | note: required by a bound in `test` --> $DIR/specialization-unconstrained.rs:17:20 @@ -22,4 +22,4 @@ LL | fn test, U>() {} error: aborting due to 1 previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0271`.