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:
bors 2023-02-03 22:37:53 +00:00
commit 886b2c3e00
44 changed files with 391 additions and 249 deletions

View file

@ -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
}

View file

@ -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);

View file

@ -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(

View file

@ -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()

View file

@ -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
}

View file

@ -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))
}

View file

@ -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>,
]);
)
}

View file

@ -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;

View 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(())
}
}

View file

@ -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 {

View file

@ -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)
}
}

View file

@ -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

View file

@ -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 };

View file

@ -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())

View file

@ -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,
},
})

View file

@ -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
}
}

View file

@ -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

View file

@ -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);

View file

@ -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
}
}

View file

@ -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]

View file

@ -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
}
};
}

View file

@ -376,8 +376,6 @@ mod bool;
mod tuple;
mod unit;
mod const_closure;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;

View file

@ -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))
}
}
}
}

View file

@ -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")]

View file

@ -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,

View file

@ -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);

View file

@ -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]

View file

@ -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!(

View file

@ -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)]

View file

@ -208,7 +208,7 @@ impl clean::GenericParamDef {
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
} else {
write!(f, ":&nbsp;{}", 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, "&nbsp;=&nbsp;{}", 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 {}:&nbsp;{}", 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, "&nbsp;=&nbsp;{}", 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("&nbsp;");
br_with_padding.push_str(" ");
}
let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
if ending == Ending::Newline {
let mut clause = "&nbsp;".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 * "&nbsp;".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>{}", "&nbsp;".repeat(indent + 4));
let close_pad = format!("<br>{}", "&nbsp;".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, ":&nbsp;{}", print_generic_bounds(bounds, cx))?;
write!(f, ": {}", print_generic_bounds(bounds, cx))?;
}
}
}

View file

@ -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(",&nbsp;");
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}:&nbsp;{t}</code>\
<code>{f}: {t}</code>\
</span>",
id = id,
f = field.name.unwrap(),

View file

@ -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;
}

View file

@ -1 +1 @@
<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>
<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T: &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>

View file

@ -1 +1 @@
<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>
<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T: &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>

View file

@ -1,4 +1,4 @@
<pre class="rust item-decl"><code>pub enum Cow2&lt;'a, B:&#160;?<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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
<pre class="rust item-decl"><code>pub enum Cow2&lt;'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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
}</code></pre>

View file

@ -1,4 +1,4 @@
<pre class="rust item-decl"><code>pub struct Struct2&lt;'a, B:&#160;?<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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
<pre class="rust item-decl"><code>pub struct Struct2&lt;'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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
}</code></pre>

View file

@ -1,3 +1,3 @@
<pre class="rust item-decl"><code>pub union Union2&lt;'a, B:&#160;?<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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
<pre class="rust item-decl"><code>pub union Union2&lt;'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>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
/* private fields */
}</code></pre>

View file

@ -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
}

View file

@ -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

View file

@ -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() {}

View file

@ -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() {}

View 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() {}

View file

@ -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`.

View file

@ -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"