Auto merge of #107650 - compiler-errors:rollup-4pntchf, r=compiler-errors
Rollup of 8 pull requests Successful merges: - #106887 (Make const/fn return params more suggestable) - #107519 (Add type alias for raw OS errors) - #107551 ( Replace `ConstFnMutClosure` with const closures ) - #107595 (Retry opening proc-macro DLLs a few times on Windows.) - #107615 (Replace nbsp in all rustdoc code blocks) - #107621 (Intern external constraints in new solver) - #107631 (loudly tell people when they change `Cargo.lock`) - #107632 (Clarifying that .map() returns None if None.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
886b2c3e00
44 changed files with 391 additions and 249 deletions
|
@ -2945,12 +2945,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
if r.is_erased() { tcx.lifetimes.re_static } else { r }
|
||||
});
|
||||
let span = ast_ty.span;
|
||||
tcx.sess.emit_err(TypeofReservedKeywordUsed {
|
||||
span,
|
||||
ty,
|
||||
opt_sugg: Some((span, Applicability::MachineApplicable))
|
||||
.filter(|_| ty.is_suggestable(tcx, false)),
|
||||
});
|
||||
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
(ty, Some((span, Applicability::MachineApplicable)))
|
||||
} else {
|
||||
(ty, None)
|
||||
};
|
||||
tcx.sess.emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
|
||||
|
||||
ty
|
||||
}
|
||||
|
|
|
@ -1199,28 +1199,22 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||
visitor.visit_ty(ty);
|
||||
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
|
||||
let ret_ty = fn_sig.output();
|
||||
if ret_ty.is_suggestable(tcx, false) {
|
||||
if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with the correct return type",
|
||||
ret_ty,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if matches!(ret_ty.kind(), ty::FnDef(..)) {
|
||||
let fn_sig = ret_ty.fn_sig(tcx);
|
||||
if fn_sig
|
||||
.skip_binder()
|
||||
.inputs_and_output
|
||||
.iter()
|
||||
.all(|t| t.is_suggestable(tcx, false))
|
||||
{
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with the correct return type",
|
||||
fn_sig,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
} else if matches!(ret_ty.kind(), ty::FnDef(..))
|
||||
&& let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false)
|
||||
{
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with the correct return type",
|
||||
fn_sig,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
|
@ -1280,9 +1274,7 @@ fn suggest_impl_trait<'tcx>(
|
|||
let trait_name = tcx.item_name(trait_def_id);
|
||||
let args_tuple = substs.type_at(1);
|
||||
let ty::Tuple(types) = *args_tuple.kind() else { return None; };
|
||||
if !types.is_suggestable(tcx, false) {
|
||||
return None;
|
||||
}
|
||||
let types = types.make_suggestable(tcx, false)?;
|
||||
let maybe_ret =
|
||||
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
|
||||
Some(format!(
|
||||
|
@ -1337,7 +1329,7 @@ fn suggest_impl_trait<'tcx>(
|
|||
// FIXME(compiler-errors): We may benefit from resolving regions here.
|
||||
if ocx.select_where_possible().is_empty()
|
||||
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
|
||||
&& item_ty.is_suggestable(tcx, false)
|
||||
&& let Some(item_ty) = item_ty.make_suggestable(tcx, false)
|
||||
&& let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
|
||||
{
|
||||
return Some(sugg);
|
||||
|
|
|
@ -8,7 +8,9 @@ use rustc_middle::hir::nested_filter;
|
|||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
|
||||
use rustc_middle::ty::{
|
||||
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
|
||||
};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
|
@ -845,37 +847,23 @@ fn infer_placeholder_type<'a>(
|
|||
) -> Ty<'a> {
|
||||
// Attempts to make the type nameable by turning FnDefs into FnPtrs.
|
||||
struct MakeNameable<'tcx> {
|
||||
success: bool,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> MakeNameable<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
MakeNameable { success: true, tcx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !self.success {
|
||||
return ty;
|
||||
}
|
||||
|
||||
match ty.kind() {
|
||||
let ty = match *ty.kind() {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id).subst(self.tcx, substs))
|
||||
self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
|
||||
}
|
||||
// FIXME: non-capturing closures should also suggest a function pointer
|
||||
ty::Closure(..) | ty::Generator(..) => {
|
||||
self.success = false;
|
||||
ty
|
||||
}
|
||||
_ => ty.super_fold_with(self),
|
||||
}
|
||||
_ => ty,
|
||||
};
|
||||
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,15 +886,11 @@ fn infer_placeholder_type<'a>(
|
|||
suggestions.clear();
|
||||
}
|
||||
|
||||
// Suggesting unnameable types won't help.
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("provide a type for the {item}", item = kind),
|
||||
format!("{colon} {sugg_ty}"),
|
||||
format!("{colon} {ty}"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
|
@ -923,15 +907,12 @@ fn infer_placeholder_type<'a>(
|
|||
let mut diag = bad_placeholder(tcx, vec![span], kind);
|
||||
|
||||
if !ty.references_error() {
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"replace with the correct type",
|
||||
sugg_ty,
|
||||
Applicability::MaybeIncorrect,
|
||||
ty,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
with_forced_trimmed_paths!(diag.span_note(
|
||||
|
|
|
@ -687,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return true;
|
||||
}
|
||||
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
|
||||
if found.is_suggestable(self.tcx, false) {
|
||||
if let Some(found) = found.make_suggestable(self.tcx, false) {
|
||||
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
|
||||
return true;
|
||||
} else if let ty::Closure(_, substs) = found.kind()
|
||||
|
|
|
@ -490,9 +490,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(output_def_id) = output_def_id
|
||||
&& let Some(trait_def_id) = trait_def_id
|
||||
&& self.tcx.parent(output_def_id) == trait_def_id
|
||||
&& output_ty.is_suggestable(self.tcx, false)
|
||||
&& let Some(output_ty) = output_ty.make_suggestable(self.tcx, false)
|
||||
{
|
||||
Some(("Output", *output_ty))
|
||||
Some(("Output", output_ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
|
|||
use proc_macro::bridge::client::ProcMacro;
|
||||
use std::ops::Fn;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use std::{cmp, env};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -689,8 +690,7 @@ impl<'a> CrateLoader<'a> {
|
|||
) -> Result<&'static [ProcMacro], CrateError> {
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
let path = env::current_dir().unwrap().join(path);
|
||||
let lib = unsafe { libloading::Library::new(path) }
|
||||
.map_err(|err| CrateError::DlOpen(err.to_string()))?;
|
||||
let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?;
|
||||
|
||||
let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
|
||||
let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) }
|
||||
|
@ -1093,3 +1093,41 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
|
|||
visit::walk_crate(&mut f, krate);
|
||||
f.spans
|
||||
}
|
||||
|
||||
// On Windows the compiler would sometimes intermittently fail to open the
|
||||
// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
|
||||
// system still holds a lock on the file, so we retry a few times before calling it
|
||||
// an error.
|
||||
fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
|
||||
assert!(max_attempts > 0);
|
||||
|
||||
let mut last_error = None;
|
||||
|
||||
for attempt in 0..max_attempts {
|
||||
match unsafe { libloading::Library::new(&path) } {
|
||||
Ok(lib) => {
|
||||
if attempt > 0 {
|
||||
debug!(
|
||||
"Loaded proc-macro `{}` after {} attempts.",
|
||||
path.display(),
|
||||
attempt + 1
|
||||
);
|
||||
}
|
||||
return Ok(lib);
|
||||
}
|
||||
Err(err) => {
|
||||
// Only try to recover from this specific error.
|
||||
if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
|
||||
return Err(err.to_string());
|
||||
}
|
||||
|
||||
last_error = Some(err);
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
|
||||
Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts))
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ macro_rules! arena_types {
|
|||
|
||||
[decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
|
||||
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
|
||||
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
|
||||
]);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
mod chalk;
|
||||
pub mod query;
|
||||
pub mod select;
|
||||
pub mod solve;
|
||||
pub mod specialization_graph;
|
||||
mod structural_impls;
|
||||
pub mod util;
|
||||
|
|
55
compiler/rustc_middle/src/traits/solve.rs
Normal file
55
compiler/rustc_middle/src/traits/solve.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_data_structures::intern::Interned;
|
||||
|
||||
use crate::ty::{FallibleTypeFolder, Ty, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
|
||||
|
||||
impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
|
||||
type Target = ExternalConstraintsData<'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
|
||||
pub struct ExternalConstraintsData<'tcx> {
|
||||
// FIXME: implement this.
|
||||
pub regions: (),
|
||||
pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ExternalConstraints<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(FallibleTypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData {
|
||||
regions: (),
|
||||
opaque_types: self
|
||||
.opaque_types
|
||||
.iter()
|
||||
.map(|opaque| opaque.try_fold_with(folder))
|
||||
.collect::<Result<_, F::Error>>()?,
|
||||
}))
|
||||
}
|
||||
|
||||
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
|
||||
TypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData {
|
||||
regions: (),
|
||||
opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<'tcx> for ExternalConstraints<'tcx> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(
|
||||
&self,
|
||||
visitor: &mut V,
|
||||
) -> std::ops::ControlFlow<V::BreakTy> {
|
||||
self.regions.visit_with(visitor)?;
|
||||
self.opaque_types.visit_with(visitor)?;
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ use crate::mir::{
|
|||
};
|
||||
use crate::thir::Thir;
|
||||
use crate::traits;
|
||||
use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use crate::ty::query::{self, TyCtxtAt};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
|
||||
|
@ -148,6 +149,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
|
||||
adt_def: InternedSet<'tcx, AdtDefData>,
|
||||
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtInterners<'tcx> {
|
||||
|
@ -169,6 +171,7 @@ impl<'tcx> CtxtInterners<'tcx> {
|
|||
bound_variable_kinds: Default::default(),
|
||||
layout: Default::default(),
|
||||
adt_def: Default::default(),
|
||||
external_constraints: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1449,6 +1452,7 @@ direct_interners! {
|
|||
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
||||
layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
|
||||
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
||||
external_constraints: intern_external_constraints(ExternalConstraintsData<'tcx>): ExternalConstraints -> ExternalConstraints<'tcx>,
|
||||
}
|
||||
|
||||
macro_rules! slice_interners {
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use crate::ty::{
|
||||
visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
|
||||
PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
|
||||
visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst,
|
||||
InferTy, Opaque, PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
|
||||
TypeSuperVisitable, TypeVisitor,
|
||||
};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait IsSuggestable<'tcx> {
|
||||
pub trait IsSuggestable<'tcx>: Sized {
|
||||
/// Whether this makes sense to suggest in a diagnostic.
|
||||
///
|
||||
/// We filter out certain types and constants since they don't provide
|
||||
|
@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> {
|
|||
/// Only if `infer_suggestable` is true, we consider type and const
|
||||
/// inference variables to be suggestable.
|
||||
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
|
||||
|
||||
fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl<'tcx, T> IsSuggestable<'tcx> for T
|
||||
where
|
||||
T: TypeVisitable<'tcx>,
|
||||
T: TypeVisitable<'tcx> + TypeFoldable<'tcx>,
|
||||
{
|
||||
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
|
||||
self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
|
||||
}
|
||||
|
||||
fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<T> {
|
||||
self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn suggest_arbitrary_trait_bound<'tcx>(
|
||||
|
@ -509,3 +516,83 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
|
|||
c.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MakeSuggestableFolder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infer_suggestable: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> FallibleTypeFolder<'tcx> for MakeSuggestableFolder<'tcx> {
|
||||
type Error = ();
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
let t = match *t.kind() {
|
||||
Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
|
||||
|
||||
FnDef(def_id, substs) => {
|
||||
self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): We could replace these with infer, I guess.
|
||||
Closure(..)
|
||||
| Infer(..)
|
||||
| Generator(..)
|
||||
| GeneratorWitness(..)
|
||||
| Bound(_, _)
|
||||
| Placeholder(_)
|
||||
| Error(_) => {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Alias(Opaque, AliasTy { def_id, .. }) => {
|
||||
let parent = self.tcx.parent(def_id);
|
||||
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
|
||||
&& let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
|
||||
&& parent_opaque_def_id == def_id
|
||||
{
|
||||
t
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
Param(param) => {
|
||||
// FIXME: It would be nice to make this not use string manipulation,
|
||||
// but it's pretty hard to do this, since `ty::ParamTy` is missing
|
||||
// sufficient info to determine if it is synthetic, and we don't
|
||||
// always have a convenient way of getting `ty::Generics` at the call
|
||||
// sites we invoke `IsSuggestable::is_suggestable`.
|
||||
if param.name.as_str().starts_with("impl ") {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
t
|
||||
}
|
||||
|
||||
_ => t,
|
||||
};
|
||||
|
||||
t.try_super_fold_with(self)
|
||||
}
|
||||
|
||||
fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ()> {
|
||||
let c = match c.kind() {
|
||||
ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c,
|
||||
|
||||
ConstKind::Infer(..)
|
||||
| ConstKind::Bound(..)
|
||||
| ConstKind::Placeholder(..)
|
||||
| ConstKind::Error(..) => {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
_ => c,
|
||||
};
|
||||
|
||||
c.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> {
|
|||
/// the infallible methods of this trait to ensure that the two APIs
|
||||
/// are coherent.
|
||||
pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
|
||||
fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
|
||||
where
|
||||
|
|
|
@ -2109,7 +2109,7 @@ impl<'a> Parser<'a> {
|
|||
ClosureBinder::NotPresent
|
||||
};
|
||||
|
||||
let constness = self.parse_constness(Case::Sensitive);
|
||||
let constness = self.parse_closure_constness(Case::Sensitive);
|
||||
|
||||
let movability =
|
||||
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
||||
|
|
|
@ -732,9 +732,10 @@ impl<'a> Parser<'a> {
|
|||
fn check_const_closure(&self) -> bool {
|
||||
self.is_keyword_ahead(0, &[kw::Const])
|
||||
&& self.look_ahead(1, |t| match &t.kind {
|
||||
token::Ident(kw::Move | kw::Static | kw::Async, _)
|
||||
| token::OrOr
|
||||
| token::BinOp(token::Or) => true,
|
||||
// async closures do not work with const closures, so we do not parse that here.
|
||||
token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
@ -1198,8 +1199,18 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses constness: `const` or nothing.
|
||||
fn parse_constness(&mut self, case: Case) -> Const {
|
||||
// Avoid const blocks to be parsed as const items
|
||||
if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
|
||||
self.parse_constness_(case, false)
|
||||
}
|
||||
|
||||
/// Parses constness for closures
|
||||
fn parse_closure_constness(&mut self, case: Case) -> Const {
|
||||
self.parse_constness_(case, true)
|
||||
}
|
||||
|
||||
fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
|
||||
// Avoid const blocks and const closures to be parsed as const items
|
||||
if (self.check_const_closure() == is_closure)
|
||||
&& self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
|
||||
&& self.eat_keyword_case(kw::Const, case)
|
||||
{
|
||||
Const::Yes(self.prev_token.uninterpolated_span())
|
||||
|
|
|
@ -24,7 +24,8 @@ use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
|||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::infer::canonical::Certainty as OldCertainty;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{
|
||||
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
|
||||
};
|
||||
|
@ -72,8 +73,7 @@ impl<'tcx, P> From<Obligation<'tcx, P>> for Goal<'tcx, P> {
|
|||
Goal { param_env: obligation.param_env, predicate: obligation.predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
|
||||
pub struct Response<'tcx> {
|
||||
pub var_values: CanonicalVarValues<'tcx>,
|
||||
/// Additional constraints returned by this query.
|
||||
|
@ -121,14 +121,6 @@ pub enum MaybeCause {
|
|||
Overflow,
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)]
|
||||
pub struct ExternalConstraints<'tcx> {
|
||||
// FIXME: implement this.
|
||||
regions: (),
|
||||
opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
|
||||
type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
|
||||
/// The result of evaluating a canonical query.
|
||||
|
@ -218,15 +210,14 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||
EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false };
|
||||
let result = ecx.compute_goal(goal);
|
||||
|
||||
// FIXME: `Response` should be `Copy`
|
||||
if search_graph.try_finalize_goal(tcx, canonical_goal, result.clone()) {
|
||||
if search_graph.try_finalize_goal(tcx, canonical_goal, result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
|
||||
let external_constraints = take_external_constraints(self.infcx)?;
|
||||
let external_constraints = compute_external_query_constraints(self.infcx)?;
|
||||
|
||||
Ok(self.infcx.canonicalize_response(Response {
|
||||
var_values: self.var_values,
|
||||
|
@ -461,18 +452,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx), ret)]
|
||||
fn take_external_constraints<'tcx>(
|
||||
fn compute_external_query_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
) -> Result<ExternalConstraints<'tcx>, NoSolution> {
|
||||
let region_obligations = infcx.take_registered_region_obligations();
|
||||
let opaque_types = infcx.take_opaque_types_for_query_response();
|
||||
Ok(ExternalConstraints {
|
||||
Ok(infcx.tcx.intern_external_constraints(ExternalConstraintsData {
|
||||
// FIXME: Now that's definitely wrong :)
|
||||
//
|
||||
// Should also do the leak check here I think
|
||||
regions: drop(region_obligations),
|
||||
opaque_types,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn instantiate_canonical_query_response<'tcx>(
|
||||
|
@ -492,7 +483,10 @@ fn instantiate_canonical_query_response<'tcx>(
|
|||
Certainty::Yes => OldCertainty::Proven,
|
||||
Certainty::Maybe(_) => OldCertainty::Ambiguous,
|
||||
},
|
||||
opaque_types: resp.external_constraints.opaque_types,
|
||||
// FIXME: This to_owned makes me sad, but we should eventually impl
|
||||
// `instantiate_query_response_and_region_obligations` separately
|
||||
// instead of piggybacking off of the old implementation.
|
||||
opaque_types: resp.external_constraints.opaque_types.to_owned(),
|
||||
value: resp.certainty,
|
||||
}),
|
||||
) else { bug!(); };
|
||||
|
@ -510,7 +504,10 @@ pub(super) fn response_no_constraints<'tcx>(
|
|||
variables: goal.variables,
|
||||
value: Response {
|
||||
var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
|
||||
external_constraints: Default::default(),
|
||||
// FIXME: maybe we should store the "no response" version in tcx, like
|
||||
// we do for tcx.types and stuff.
|
||||
external_constraints: tcx
|
||||
.intern_external_constraints(ExternalConstraintsData::default()),
|
||||
certainty,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -95,8 +95,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
|
|||
}
|
||||
|
||||
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
|
||||
// FIXME: Responses should probably be `Copy` as well
|
||||
self.entries[entry_index].response.clone()
|
||||
self.entries[entry_index].response
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::const_closure::ConstFnMutClosure;
|
||||
use crate::marker::Destruct;
|
||||
|
||||
use self::Ordering::*;
|
||||
|
@ -1291,17 +1290,7 @@ where
|
|||
F: ~const Destruct,
|
||||
K: ~const Destruct,
|
||||
{
|
||||
const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
|
||||
f: &mut F,
|
||||
(v1, v2): (&T, &T),
|
||||
) -> Ordering
|
||||
where
|
||||
T: ~const Destruct,
|
||||
K: ~const Destruct,
|
||||
{
|
||||
f(v1).cmp(&f(v2))
|
||||
}
|
||||
max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
|
||||
max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
|
||||
}
|
||||
|
||||
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
use crate::marker::Destruct;
|
||||
use crate::marker::Tuple;
|
||||
|
||||
/// Struct representing a closure with mutably borrowed data.
|
||||
///
|
||||
/// Example:
|
||||
/// ```no_build
|
||||
/// #![feature(const_mut_refs)]
|
||||
/// use crate::const_closure::ConstFnMutClosure;
|
||||
/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 {
|
||||
/// *state += arg;
|
||||
/// *state
|
||||
/// }
|
||||
/// let mut i = 5;
|
||||
/// let mut cl = ConstFnMutClosure::new(&mut i, imp);
|
||||
///
|
||||
/// assert!(7 == cl(2));
|
||||
/// assert!(8 == cl(1));
|
||||
/// ```
|
||||
pub(crate) struct ConstFnMutClosure<CapturedData, Function> {
|
||||
/// The Data captured by the Closure.
|
||||
/// Must be either a (mutable) reference or a tuple of (mutable) references.
|
||||
pub data: CapturedData,
|
||||
/// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn
|
||||
pub func: Function,
|
||||
}
|
||||
impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> {
|
||||
/// Function for creating a new closure.
|
||||
///
|
||||
/// `data` is the a mutable borrow of data that is captured from the environment.
|
||||
/// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually.
|
||||
///
|
||||
/// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
|
||||
/// and return the return value of the closure.
|
||||
pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
|
||||
data: &'a mut CapturedData,
|
||||
func: Function,
|
||||
) -> Self
|
||||
where
|
||||
Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
|
||||
{
|
||||
Self { data, func }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_fn_mut_tuple {
|
||||
($($var:ident)*) => {
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
|
||||
FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
where
|
||||
Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
|
||||
{
|
||||
type Output = ClosureReturnValue;
|
||||
|
||||
extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
|
||||
self.call_mut(args)
|
||||
}
|
||||
}
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
|
||||
FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
where
|
||||
Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
|
||||
#[allow(non_snake_case)]
|
||||
let ($($var),*) = &mut self.data;
|
||||
(self.func)(($($var),*), args)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_fn_mut_tuple!(A);
|
||||
impl_fn_mut_tuple!(A B);
|
||||
impl_fn_mut_tuple!(A B C);
|
||||
impl_fn_mut_tuple!(A B C D);
|
||||
impl_fn_mut_tuple!(A B C D E);
|
|
@ -1,5 +1,4 @@
|
|||
use crate::array;
|
||||
use crate::const_closure::ConstFnMutClosure;
|
||||
use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce};
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
|
||||
|
@ -189,13 +188,12 @@ where
|
|||
I: Iterator,
|
||||
{
|
||||
#[inline]
|
||||
default fn fold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
default fn fold<B, F>(mut self, init: B, f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp);
|
||||
self.try_fold(init, fold).0
|
||||
self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use crate::{
|
||||
const_closure::ConstFnMutClosure,
|
||||
ops::{NeverShortCircuit, Try},
|
||||
};
|
||||
use crate::ops::{NeverShortCircuit, Try};
|
||||
|
||||
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
|
||||
///
|
||||
|
@ -39,13 +36,12 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<B, F>(self, init: B, mut f: F) -> B
|
||||
fn fold<B, F>(self, init: B, f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
// `fold` needs ownership, so this can't forward directly.
|
||||
I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
|
||||
.0
|
||||
I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -76,17 +72,12 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<B, F>(self, init: B, mut f: F) -> B
|
||||
fn rfold<B, F>(self, init: B, f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
// `rfold` needs ownership, so this can't forward directly.
|
||||
I::try_rfold(
|
||||
self.0,
|
||||
init,
|
||||
ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
|
||||
)
|
||||
.0
|
||||
I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -362,15 +362,13 @@ macro_rules! impl_fold_via_try_fold {
|
|||
};
|
||||
(@internal $fold:ident -> $try_fold:ident) => {
|
||||
#[inline]
|
||||
fn $fold<AAA, FFF>(mut self, init: AAA, mut fold: FFF) -> AAA
|
||||
fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
|
||||
where
|
||||
FFF: FnMut(AAA, Self::Item) -> AAA,
|
||||
{
|
||||
use crate::const_closure::ConstFnMutClosure;
|
||||
use crate::ops::NeverShortCircuit;
|
||||
|
||||
let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp);
|
||||
self.$try_fold(init, fold).0
|
||||
self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -376,8 +376,6 @@ mod bool;
|
|||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
mod const_closure;
|
||||
|
||||
#[stable(feature = "core_primitive", since = "1.43.0")]
|
||||
pub mod primitive;
|
||||
|
||||
|
|
|
@ -379,13 +379,18 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
|
|||
pub(crate) struct NeverShortCircuit<T>(pub T);
|
||||
|
||||
impl<T> NeverShortCircuit<T> {
|
||||
/// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
|
||||
#[inline]
|
||||
pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
|
||||
f: &mut F,
|
||||
(a, b): (A, B),
|
||||
) -> NeverShortCircuit<T> {
|
||||
NeverShortCircuit(f(a, b))
|
||||
pub fn wrap_mut_2<A, B>(
|
||||
mut f: impl ~const FnMut(A, B) -> T,
|
||||
) -> impl ~const FnMut(A, B) -> Self {
|
||||
cfg_if! {
|
||||
if #[cfg(bootstrap)] {
|
||||
#[allow(unused_parens)]
|
||||
(const move |a, b| NeverShortCircuit(f(a, b)))
|
||||
} else {
|
||||
const move |a, b| NeverShortCircuit(f(a, b))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -943,7 +943,7 @@ impl<T> Option<T> {
|
|||
// Transforming contained values
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value.
|
||||
/// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value (if `Some`) or returns `None` (if `None`).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -955,8 +955,10 @@ impl<T> Option<T> {
|
|||
/// let maybe_some_string = Some(String::from("Hello, World!"));
|
||||
/// // `Option::map` takes self *by value*, consuming `maybe_some_string`
|
||||
/// let maybe_some_len = maybe_some_string.map(|s| s.len());
|
||||
///
|
||||
/// assert_eq!(maybe_some_len, Some(13));
|
||||
///
|
||||
/// let x: Option<&str> = None;
|
||||
/// assert_eq!(x.map(|s| s.len()), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -88,12 +88,23 @@ impl From<alloc::ffi::NulError> for Error {
|
|||
// doesn't accidentally get printed.
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
enum ErrorData<C> {
|
||||
Os(i32),
|
||||
Os(RawOsError),
|
||||
Simple(ErrorKind),
|
||||
SimpleMessage(&'static SimpleMessage),
|
||||
Custom(C),
|
||||
}
|
||||
|
||||
/// The type of raw OS error codes returned by [`Error::raw_os_error`].
|
||||
///
|
||||
/// This is an [`i32`] on all currently supported platforms, but platforms
|
||||
/// added in the future (such as UEFI) may use a different primitive type like
|
||||
/// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum
|
||||
/// portability.
|
||||
///
|
||||
/// [`into`]: Into::into
|
||||
#[unstable(feature = "raw_os_error_ty", issue = "none")]
|
||||
pub type RawOsError = i32;
|
||||
|
||||
// `#[repr(align(4))]` is probably redundant, it should have that value or
|
||||
// higher already. We include it just because repr_bitpacked.rs's encoding
|
||||
// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the
|
||||
|
@ -579,7 +590,7 @@ impl Error {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub fn last_os_error() -> Error {
|
||||
Error::from_raw_os_error(sys::os::errno() as i32)
|
||||
Error::from_raw_os_error(sys::os::errno())
|
||||
}
|
||||
|
||||
/// Creates a new instance of an [`Error`] from a particular OS error code.
|
||||
|
@ -610,7 +621,7 @@ impl Error {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn from_raw_os_error(code: i32) -> Error {
|
||||
pub fn from_raw_os_error(code: RawOsError) -> Error {
|
||||
Error { repr: Repr::new_os(code) }
|
||||
}
|
||||
|
||||
|
@ -646,7 +657,7 @@ impl Error {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn raw_os_error(&self) -> Option<i32> {
|
||||
pub fn raw_os_error(&self) -> Option<RawOsError> {
|
||||
match self.repr.data() {
|
||||
ErrorData::Os(i) => Some(i),
|
||||
ErrorData::Custom(..) => None,
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
//! to use a pointer type to store something that may hold an integer, some of
|
||||
//! the time.
|
||||
|
||||
use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
|
||||
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
|
||||
use alloc::boxed::Box;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{align_of, size_of};
|
||||
|
@ -172,7 +172,7 @@ impl Repr {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn new_os(code: i32) -> Self {
|
||||
pub(super) fn new_os(code: RawOsError) -> Self {
|
||||
let utagged = ((code as usize) << 32) | TAG_OS;
|
||||
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
|
||||
let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData);
|
||||
|
@ -250,7 +250,7 @@ where
|
|||
let bits = ptr.as_ptr().addr();
|
||||
match bits & TAG_MASK {
|
||||
TAG_OS => {
|
||||
let code = ((bits as i64) >> 32) as i32;
|
||||
let code = ((bits as i64) >> 32) as RawOsError;
|
||||
ErrorData::Os(code)
|
||||
}
|
||||
TAG_SIMPLE => {
|
||||
|
@ -374,6 +374,9 @@ static_assert!((TAG_MASK + 1).is_power_of_two());
|
|||
static_assert!(align_of::<SimpleMessage>() >= TAG_MASK + 1);
|
||||
static_assert!(align_of::<Custom>() >= TAG_MASK + 1);
|
||||
|
||||
// `RawOsError` must be an alias for `i32`.
|
||||
const _: fn(RawOsError) -> i32 = |os| os;
|
||||
|
||||
static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE_MESSAGE, TAG_SIMPLE_MESSAGE);
|
||||
static_assert!(@usize_eq: TAG_MASK & TAG_CUSTOM, TAG_CUSTOM);
|
||||
static_assert!(@usize_eq: TAG_MASK & TAG_OS, TAG_OS);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//! non-64bit targets, where the packed 64 bit representation wouldn't work, and
|
||||
//! would have no benefit.
|
||||
|
||||
use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
|
||||
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
|
||||
use alloc::boxed::Box;
|
||||
|
||||
type Inner = ErrorData<Box<Custom>>;
|
||||
|
@ -18,7 +18,7 @@ impl Repr {
|
|||
Self(Inner::Custom(b))
|
||||
}
|
||||
#[inline]
|
||||
pub(super) fn new_os(code: i32) -> Self {
|
||||
pub(super) fn new_os(code: RawOsError) -> Self {
|
||||
Self(Inner::Os(code))
|
||||
}
|
||||
#[inline]
|
||||
|
|
|
@ -71,7 +71,7 @@ fn test_const() {
|
|||
|
||||
#[test]
|
||||
fn test_os_packing() {
|
||||
for code in -20i32..20i32 {
|
||||
for code in -20..20 {
|
||||
let e = Error::from_raw_os_error(code);
|
||||
assert_eq!(e.raw_os_error(), Some(code));
|
||||
assert_matches!(
|
||||
|
|
|
@ -262,6 +262,8 @@ use crate::sys_common::memchr;
|
|||
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub use self::buffered::WriterPanicked;
|
||||
#[unstable(feature = "raw_os_error_ty", issue = "none")]
|
||||
pub use self::error::RawOsError;
|
||||
pub(crate) use self::stdio::attempt_print_to_stderr;
|
||||
#[unstable(feature = "internal_output_capture", issue = "none")]
|
||||
#[doc(no_inline, hidden)]
|
||||
|
|
|
@ -208,7 +208,7 @@ impl clean::GenericParamDef {
|
|||
if f.alternate() {
|
||||
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
|
||||
} else {
|
||||
write!(f, ": {}", print_generic_bounds(bounds, cx))?;
|
||||
write!(f, ": {}", print_generic_bounds(bounds, cx))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ impl clean::GenericParamDef {
|
|||
if f.alternate() {
|
||||
write!(f, " = {:#}", ty.print(cx))?;
|
||||
} else {
|
||||
write!(f, " = {}", ty.print(cx))?;
|
||||
write!(f, " = {}", ty.print(cx))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,14 +226,14 @@ impl clean::GenericParamDef {
|
|||
if f.alternate() {
|
||||
write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
|
||||
} else {
|
||||
write!(f, "const {}: {}", self.name, ty.print(cx))?;
|
||||
write!(f, "const {}: {}", self.name, ty.print(cx))?;
|
||||
}
|
||||
|
||||
if let Some(default) = default {
|
||||
if f.alternate() {
|
||||
write!(f, " = {:#}", default)?;
|
||||
} else {
|
||||
write!(f, " = {}", default)?;
|
||||
write!(f, " = {}", default)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,12 +354,12 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
|||
let mut br_with_padding = String::with_capacity(6 * indent + 28);
|
||||
br_with_padding.push_str("<br>");
|
||||
for _ in 0..indent + 4 {
|
||||
br_with_padding.push_str(" ");
|
||||
br_with_padding.push_str(" ");
|
||||
}
|
||||
let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
|
||||
|
||||
if ending == Ending::Newline {
|
||||
let mut clause = " ".repeat(indent.saturating_sub(1));
|
||||
let mut clause = " ".repeat(indent.saturating_sub(1));
|
||||
write!(clause, "<span class=\"where fmt-newline\">where{where_preds},</span>")?;
|
||||
clause
|
||||
} else {
|
||||
|
@ -368,7 +368,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
|||
format!("<br><span class=\"where\">where{where_preds}</span>")
|
||||
} else {
|
||||
let mut clause = br_with_padding;
|
||||
clause.truncate(clause.len() - 4 * " ".len());
|
||||
clause.truncate(clause.len() - 4);
|
||||
write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
|
||||
clause
|
||||
}
|
||||
|
@ -1391,8 +1391,8 @@ impl clean::FnDecl {
|
|||
|
||||
let declaration_len = header_len + args_plain.len() + arrow_plain.len();
|
||||
let output = if declaration_len > 80 {
|
||||
let full_pad = format!("<br>{}", " ".repeat(indent + 4));
|
||||
let close_pad = format!("<br>{}", " ".repeat(indent));
|
||||
let full_pad = format!("<br>{}", " ".repeat(indent + 4));
|
||||
let close_pad = format!("<br>{}", " ".repeat(indent));
|
||||
format!(
|
||||
"({pad}{args}{close}){arrow}",
|
||||
pad = if self.inputs.values.is_empty() { "" } else { &full_pad },
|
||||
|
@ -1611,7 +1611,7 @@ impl clean::TypeBinding {
|
|||
if f.alternate() {
|
||||
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
|
||||
} else {
|
||||
write!(f, ": {}", print_generic_bounds(bounds, cx))?;
|
||||
write!(f, ": {}", print_generic_bounds(bounds, cx))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1157,7 +1157,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
|||
fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
|
||||
for (i, ty) in s.iter().enumerate() {
|
||||
if i > 0 {
|
||||
w.write_str(", ");
|
||||
w.write_str(", ");
|
||||
}
|
||||
match *ty.kind {
|
||||
clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
|
||||
|
@ -1297,7 +1297,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
|
|||
"<div class=\"sub-variant-field\">\
|
||||
<span id=\"{id}\" class=\"small-section-header\">\
|
||||
<a href=\"#{id}\" class=\"anchor field\">§</a>\
|
||||
<code>{f}: {t}</code>\
|
||||
<code>{f}: {t}</code>\
|
||||
</span>",
|
||||
id = id,
|
||||
f = field.name.unwrap(),
|
||||
|
|
|
@ -184,6 +184,7 @@ h4.code-header {
|
|||
font-weight: 600;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
#crate-search,
|
||||
|
@ -642,6 +643,7 @@ pre, .rustdoc.source .example-wrap {
|
|||
.fn .where,
|
||||
.where.fmt-newline {
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
|
||||
<script type="text/json" id="notable-traits-data">{"SomeStruct":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></code></h3><pre><code><span class=\"where fmt-newline\">impl <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\">SomeStruct</a></span>","Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T: <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
|
|
@ -1 +1 @@
|
|||
<script type="text/json" id="notable-traits-data">{"Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T:&nbsp;<a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
|
||||
<script type="text/json" id="notable-traits-data">{"Wrapper<Self>":"<h3>Notable traits for <code><a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</code></h3><pre><code><span class=\"where fmt-newline\">impl&lt;T: <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a>&gt; <a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\">SomeTrait</a> for <a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\">Wrapper</a>&lt;T&gt;</span>"}</script>
|
|
@ -1,4 +1,4 @@
|
|||
<pre class="rust item-decl"><code>pub enum Cow2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
<pre class="rust item-decl"><code>pub enum Cow2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>),
|
||||
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
|
||||
}</code></pre>
|
|
@ -1,4 +1,4 @@
|
|||
<pre class="rust item-decl"><code>pub struct Struct2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
<pre class="rust item-decl"><code>pub struct Struct2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a B</a>,
|
||||
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
|
||||
}</code></pre>
|
|
@ -1,3 +1,3 @@
|
|||
<pre class="rust item-decl"><code>pub union Union2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
<pre class="rust item-decl"><code>pub union Union2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> {
|
||||
/* private fields */
|
||||
}</code></pre>
|
|
@ -7,6 +7,6 @@ fn main() {
|
|||
enum Foo { Bar }
|
||||
fn foo(x: impl Iterator<Item = Foo>) {
|
||||
for <Foo>::Bar in x {}
|
||||
//~^ ERROR expected one of `const`, `move`, `static`, `|`
|
||||
//~^ ERROR expected one of `move`, `static`, `|`
|
||||
//~^^ ERROR `for<...>` binders for closures are experimental
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::`
|
||||
error: expected one of `move`, `static`, `|`, or `||`, found `::`
|
||||
--> $DIR/recover-quantified-closure.rs:9:14
|
||||
|
|
||||
LL | for <Foo>::Bar in x {}
|
||||
| ^^ expected one of `const`, `move`, `static`, `|`, or `||`
|
||||
| ^^ expected one of `move`, `static`, `|`, or `||`
|
||||
|
||||
error[E0658]: `for<...>` binders for closures are experimental
|
||||
--> $DIR/recover-quantified-closure.rs:2:5
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(const_trait_impl, const_closures)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
const fn test() -> impl ~const Fn() {
|
||||
const move || {}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
fn bar() -> Wrapper<fn()> { Wrapper(foo) }
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn foo() {}
|
||||
|
||||
fn main() {}
|
12
tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs
Normal file
12
tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
fn bar() -> _ { Wrapper(foo) }
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
|
||||
fn foo() {}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/suggest-fn-ptr-for-fn-item-in-fn-ret.rs:7:13
|
||||
|
|
||||
LL | fn bar() -> _ { Wrapper(foo) }
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `Wrapper<fn()>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
|
@ -250,7 +250,8 @@ new_pr = true
|
|||
|
||||
[autolabel."WG-trait-system-refactor"]
|
||||
trigger_files = [
|
||||
"compiler/rustc_trait_selection/src/solve"
|
||||
"compiler/rustc_trait_selection/src/solve",
|
||||
"compiler/rustc_middle/src/traits/solve.rs"
|
||||
]
|
||||
|
||||
[notify-zulip."I-prioritize"]
|
||||
|
@ -459,6 +460,14 @@ These commits modify **compiler targets**.
|
|||
[mentions."src/doc/style-guide"]
|
||||
cc = ["@rust-lang/style"]
|
||||
|
||||
[mentions."Cargo.lock"]
|
||||
message = """
|
||||
These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
|
||||
This was probably unintentional and should be reverted before this PR is merged.
|
||||
|
||||
If this was intentional then you can ignore this comment.
|
||||
"""
|
||||
|
||||
[assign]
|
||||
warn_non_default_branch = true
|
||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html"
|
||||
|
|
Loading…
Add table
Reference in a new issue