Auto merge of #140324 - matthiaskrgr:rollup-jlzvdre, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #139865 (Stabilize proc_macro::Span::{start,end,line,column}.) - #140086 (If creating a temporary directory fails with permission denied then retry with backoff) - #140216 (Document that "extern blocks must be unsafe" in Rust 2024) - #140253 (Add XtensaAsmPrinter) - #140272 (Improve error message for `||` (or) in let chains) - #140305 (Track per-obligation recursion depth only if there is inference in the new solver) - #140306 (handle specialization in the new trait solver) - #140308 (stall generator witness obligations: add regression test) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5ae50d3b21
45 changed files with 526 additions and 139 deletions
|
|
@ -3700,6 +3700,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "rustc_fs_util"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_graphviz"
|
||||
|
|
@ -4012,7 +4015,6 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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| {
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
tempfile = "3.7.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -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<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
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<S: AsRef<OsStr> + ?Sized>(&mut self, prefix: &'a S) -> &mut Self {
|
||||
self.builder.prefix(prefix);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn suffix<S: AsRef<OsStr> + ?Sized>(&mut self, suffix: &'b S) -> &mut Self {
|
||||
self.builder.suffix(suffix);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tempdir_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<TempDir> {
|
||||
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<TempDir> {
|
||||
self.tempdir_in(env::temp_dir())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ pub fn initialize_available_targets() {
|
|||
LLVMInitializeXtensaTargetInfo,
|
||||
LLVMInitializeXtensaTarget,
|
||||
LLVMInitializeXtensaTargetMC,
|
||||
LLVMInitializeXtensaAsmPrinter,
|
||||
LLVMInitializeXtensaAsmParser
|
||||
);
|
||||
init_target!(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<D, I> EvalCtxt<'_, D>
|
||||
where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
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<Candidate<I>>,
|
||||
) {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,17 @@ fn has_no_inference_or_external_constraints<I: Interner>(
|
|||
&& normalization_nested_goals.is_empty()
|
||||
}
|
||||
|
||||
fn has_only_region_constraints<I: Interner>(response: ty::Canonical<I, Response<I>>) -> 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<Interner = I>,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -478,6 +478,13 @@ pub(crate) struct ExpectedExpressionFoundLet {
|
|||
pub comparison: Option<MaybeComparison>,
|
||||
}
|
||||
|
||||
#[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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -163,15 +163,15 @@ where
|
|||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Self, ty::TraitRef<Self>>;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
|||
25
tests/ui/coroutine/dont-drop-stalled-generators.rs
Normal file
25
tests/ui/coroutine/dont-drop-stalled-generators.rs
Normal file
|
|
@ -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<T>(*const T);
|
||||
|
||||
impl<T: Send> Clone for W<T> {
|
||||
fn clone(&self) -> Self { W(self.0) }
|
||||
}
|
||||
|
||||
impl<T: Send> Copy for W<T> {}
|
||||
|
||||
fn main() {
|
||||
let coro = async {};
|
||||
let x = W(&raw const coro);
|
||||
let c = || {
|
||||
let x = x;
|
||||
};
|
||||
}
|
||||
28
tests/ui/parser/or-in-let-chain.edition2021.stderr
Normal file
28
tests/ui/parser/or-in-let-chain.edition2021.stderr
Normal file
|
|
@ -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
|
||||
|
||||
28
tests/ui/parser/or-in-let-chain.edition2024.stderr
Normal file
28
tests/ui/parser/or-in-let-chain.edition2024.stderr
Normal file
|
|
@ -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
|
||||
|
||||
17
tests/ui/parser/or-in-let-chain.rs
Normal file
17
tests/ui/parser/or-in-let-chain.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
fn let_or_guard(x: Result<Option<i32>, ()>) {
|
||||
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
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 => {}
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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
|
||||
|
||||
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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
|
||||
|
||||
|
|
@ -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<T: 'static> WithAssoc for (T,) {
|
||||
type Assoc = ();
|
||||
}
|
||||
|
||||
struct GenericArray<U: WithAssoc>(U::Assoc);
|
||||
|
||||
trait AbiExample {
|
||||
fn example();
|
||||
}
|
||||
impl<U: WithAssoc> AbiExample for GenericArray<U> {
|
||||
fn example() {}
|
||||
}
|
||||
impl<T> AbiExample for T {
|
||||
default fn example() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = GenericArray::<((),)>::example();
|
||||
}
|
||||
|
|
@ -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<T>() -> <T as Foo>::Assoc {
|
||||
| ----------------- expected `<T as Foo>::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
|
||||
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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<T>() -> <T as Foo>::Assoc {
|
||||
| ----------------- expected `<T as Foo>::Assoc` because of return type
|
||||
...
|
||||
LL | ()
|
||||
| ^^ types differ
|
||||
|
|
||||
= note: expected associated type `<T as Foo>::Assoc`
|
||||
found unit type `()`
|
||||
= help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<T>;
|
||||
| ----------------------------- associated type is `default` and may be overridden
|
||||
|
|
@ -22,7 +22,7 @@ LL | Box::new(self)
|
|||
found struct `Box<T>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:25:5
|
||||
--> $DIR/specialization-default-types.rs:29:5
|
||||
|
|
||||
LL | fn trouble<T>(t: T) -> Box<T> {
|
||||
| ------ expected `Box<T>` because of return type
|
||||
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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<T>;
|
||||
| ----------------------------- associated type is `default` and may be overridden
|
||||
LL | default fn generate(self) -> Self::Output {
|
||||
| ------------ expected `<T as Example>::Output` because of return type
|
||||
LL | Box::new(self)
|
||||
| ^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected associated type `<T as Example>::Output`
|
||||
found struct `Box<T>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/specialization-default-types.rs:29:5
|
||||
|
|
||||
LL | fn trouble<T>(t: T) -> Box<T> {
|
||||
| ------ expected `Box<T>` because of return type
|
||||
LL | Example::generate(t)
|
||||
| ^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected struct `Box<T>`
|
||||
found associated type `<T as Example>::Output`
|
||||
= help: consider constraining the associated type `<T as Example>::Output` to `Box<T>`
|
||||
= 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`.
|
||||
|
|
@ -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?
|
||||
|
|
|
|||
31
tests/ui/traits/next-solver/coerce-depth.rs
Normal file
31
tests/ui/traits/next-solver/coerce-depth.rs
Normal file
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
|
|
@ -10,11 +10,8 @@ trait Default {
|
|||
|
||||
impl<T> 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 `<T as Default>::Id: '_`
|
||||
self //~ ERROR cannot satisfy
|
||||
self //~ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +22,7 @@ fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
|||
use std::num::NonZero;
|
||||
|
||||
fn main() {
|
||||
let s = transmute::<u8, Option<NonZero<u8>>>(0); //~ ERROR cannot satisfy
|
||||
let s = transmute::<u8, Option<NonZero<u8>>>(0);
|
||||
//~^ ERROR type mismatch resolving `<u8 as Default>::Id == Option<NonZero<u8>>`
|
||||
assert_eq!(s, None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 `<T as Default>::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 `&<T as Default>::Id`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T`
|
||||
--> $DIR/specialization-transmute.rs:17:9
|
||||
|
|
||||
| --------- expected `&<T as Default>::Id` because of return type
|
||||
LL | self
|
||||
| ^^^^ cannot satisfy `<T as Default>::Id normalizes-to T`
|
||||
| ^^^^ types differ
|
||||
|
|
||||
= note: expected reference `&<T as Default>::Id`
|
||||
found reference `&T`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
|
||||
--> $DIR/specialization-transmute.rs:28:13
|
||||
error[E0271]: type mismatch resolving `<u8 as Default>::Id == Option<NonZero<u8>>`
|
||||
--> $DIR/specialization-transmute.rs:25:50
|
||||
|
|
||||
LL | let s = transmute::<u8, Option<NonZero<u8>>>(0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
|
||||
| ------------------------------------ ^ 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<T: Default<Id = U>, 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`.
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}
|
|||
|
||||
fn main() {
|
||||
test::<u32, ()>();
|
||||
//~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
|
||||
//~^ ERROR type mismatch resolving `<u32 as Default>::Id == ()`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 `<u32 as Default>::Id normalizes-to ()`
|
||||
--> $DIR/specialization-unconstrained.rs:20:5
|
||||
error[E0271]: type mismatch resolving `<u32 as Default>::Id == ()`
|
||||
--> $DIR/specialization-unconstrained.rs:20:12
|
||||
|
|
||||
LL | test::<u32, ()>();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::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<T: Default<Id = U>, 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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue