mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #109720 - Dylan-DPC:rollup-u564m8s, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #108335 (rustdoc + rustdoc-json support for `feature(non_lifetime_binders)`) - #109534 (rustdoc: Unsupport importing `doc(primitive)` and `doc(keyword)` modules) - #109659 (llvm-wrapper: adapt for LLVM API change) - #109664 (Use span of placeholders in format_args!() expansion.) - #109683 (Check for overflow in `assemble_candidates_after_normalizing_self_ty`) - #109713 (Fix mismatched punctuation in Debug impl of AttrId) - #109718 (Rename `IndexVec::last` → `last_index`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
cf32b9de1e
@ -2570,7 +2570,7 @@ pub enum AttrStyle {
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[custom_encodable]
|
||||
#[debug_format = "AttrId({})]"]
|
||||
#[debug_format = "AttrId({})"]
|
||||
pub struct AttrId {}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use super::LoweringContext;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_span::{
|
||||
sym,
|
||||
@ -238,7 +238,7 @@ fn make_count<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
sp: Span,
|
||||
count: &Option<FormatCount>,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
|
||||
) -> hir::Expr<'hir> {
|
||||
match count {
|
||||
Some(FormatCount::Literal(n)) => {
|
||||
@ -252,7 +252,7 @@ fn make_count<'hir>(
|
||||
}
|
||||
Some(FormatCount::Argument(arg)) => {
|
||||
if let Ok(arg_index) = arg.index {
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize), arg.span);
|
||||
let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
|
||||
sp,
|
||||
hir::LangItem::FormatCount,
|
||||
@ -291,12 +291,14 @@ fn make_format_spec<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
sp: Span,
|
||||
placeholder: &FormatPlaceholder,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
|
||||
) -> hir::Expr<'hir> {
|
||||
let position = match placeholder.argument.index {
|
||||
Ok(arg_index) => {
|
||||
let (i, _) =
|
||||
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
|
||||
let (i, _) = argmap.insert_full(
|
||||
(arg_index, ArgumentType::Format(placeholder.format_trait)),
|
||||
placeholder.span,
|
||||
);
|
||||
ctx.expr_usize(sp, i)
|
||||
}
|
||||
Err(_) => ctx.expr(
|
||||
@ -386,7 +388,7 @@ fn expand_format_args<'hir>(
|
||||
|
||||
// Create a list of all _unique_ (argument, format trait) combinations.
|
||||
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
|
||||
let mut argmap = FxIndexSet::default();
|
||||
let mut argmap = FxIndexMap::default();
|
||||
for piece in &fmt.template {
|
||||
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
|
||||
if placeholder.format_options != Default::default() {
|
||||
@ -394,7 +396,10 @@ fn expand_format_args<'hir>(
|
||||
use_format_options = true;
|
||||
}
|
||||
if let Ok(index) = placeholder.argument.index {
|
||||
if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
|
||||
if argmap
|
||||
.insert((index, ArgumentType::Format(placeholder.format_trait)), placeholder.span)
|
||||
.is_some()
|
||||
{
|
||||
// Duplicate (argument, format trait) combination,
|
||||
// which we'll only put once in the args array.
|
||||
use_format_options = true;
|
||||
@ -438,7 +443,7 @@ fn expand_format_args<'hir>(
|
||||
// This is an optimization, speeding up compilation about 1-2% in some cases.
|
||||
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
|
||||
let use_simple_array = argmap.len() == arguments.len()
|
||||
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
|
||||
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
|
||||
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
|
||||
|
||||
let args = if use_simple_array {
|
||||
@ -452,14 +457,19 @@ fn expand_format_args<'hir>(
|
||||
let elements: Vec<_> = arguments
|
||||
.iter()
|
||||
.zip(argmap)
|
||||
.map(|(arg, (_, ty))| {
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
.map(|(arg, ((_, ty), placeholder_span))| {
|
||||
let placeholder_span =
|
||||
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
|
||||
let arg_span = match arg.kind {
|
||||
FormatArgumentKind::Captured(_) => placeholder_span,
|
||||
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
|
||||
};
|
||||
let arg = ctx.lower_expr(&arg.expr);
|
||||
let ref_arg = ctx.arena.alloc(ctx.expr(
|
||||
sp,
|
||||
arg_span,
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
|
||||
));
|
||||
make_argument(ctx, sp, ref_arg, ty)
|
||||
make_argument(ctx, placeholder_span, ref_arg, ty)
|
||||
})
|
||||
.collect();
|
||||
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
|
||||
@ -475,16 +485,26 @@ fn expand_format_args<'hir>(
|
||||
// }
|
||||
let args_ident = Ident::new(sym::args, macsp);
|
||||
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
|
||||
let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| {
|
||||
let arg = &arguments[arg_index];
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
|
||||
let arg = ctx.arena.alloc(ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Field(args_ident_expr, Ident::new(sym::integer(arg_index), macsp)),
|
||||
));
|
||||
make_argument(ctx, sp, arg, ty)
|
||||
}));
|
||||
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
|
||||
|(&(arg_index, ty), &placeholder_span)| {
|
||||
let arg = &arguments[arg_index];
|
||||
let placeholder_span =
|
||||
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
|
||||
let arg_span = match arg.kind {
|
||||
FormatArgumentKind::Captured(_) => placeholder_span,
|
||||
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
|
||||
};
|
||||
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
|
||||
let arg = ctx.arena.alloc(ctx.expr(
|
||||
arg_span,
|
||||
hir::ExprKind::Field(
|
||||
args_ident_expr,
|
||||
Ident::new(sym::integer(arg_index), macsp),
|
||||
),
|
||||
));
|
||||
make_argument(ctx, placeholder_span, arg, ty)
|
||||
},
|
||||
));
|
||||
let elements: Vec<_> = arguments
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
|
@ -707,7 +707,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) {
|
||||
let last = self.promoted.basic_blocks.last().unwrap();
|
||||
let last = self.promoted.basic_blocks.last_index().unwrap();
|
||||
let data = &mut self.promoted[last];
|
||||
data.statements.push(Statement {
|
||||
source_info: SourceInfo::outermost(span),
|
||||
@ -800,7 +800,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
self.visit_operand(arg, loc);
|
||||
}
|
||||
|
||||
let last = self.promoted.basic_blocks.last().unwrap();
|
||||
let last = self.promoted.basic_blocks.last_index().unwrap();
|
||||
let new_target = self.new_block();
|
||||
|
||||
*self.promoted[last].terminator_mut() = Terminator {
|
||||
|
@ -216,7 +216,7 @@ impl<I: Idx, T> IndexVec<I, T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn last(&self) -> Option<I> {
|
||||
pub fn last_index(&self) -> Option<I> {
|
||||
self.len().checked_sub(1).map(I::new)
|
||||
}
|
||||
|
||||
|
@ -1163,13 +1163,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
|
||||
// Otherwise, we sometimes lose `static` values -- see #60184.
|
||||
computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
|
||||
deadIsPrevailing, /* ImportEnabled = */ false);
|
||||
ComputeCrossModuleImport(
|
||||
Ret->Index,
|
||||
Ret->ModuleToDefinedGVSummaries,
|
||||
Ret->ImportLists,
|
||||
Ret->ExportLists
|
||||
);
|
||||
|
||||
// Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
|
||||
// impacts the caching.
|
||||
//
|
||||
@ -1186,6 +1179,16 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
|
||||
return true;
|
||||
return Prevailing->second == S;
|
||||
};
|
||||
ComputeCrossModuleImport(
|
||||
Ret->Index,
|
||||
Ret->ModuleToDefinedGVSummaries,
|
||||
#if LLVM_VERSION_GE(17, 0)
|
||||
isPrevailing,
|
||||
#endif
|
||||
Ret->ImportLists,
|
||||
Ret->ExportLists
|
||||
);
|
||||
|
||||
auto recordNewLinkage = [&](StringRef ModuleIdentifier,
|
||||
GlobalValue::GUID GUID,
|
||||
GlobalValue::LinkageTypes NewLinkage) {
|
||||
|
@ -65,7 +65,7 @@ impl<'tcx> MockBlocks<'tcx> {
|
||||
}
|
||||
|
||||
fn push(&mut self, kind: TerminatorKind<'tcx>) -> BasicBlock {
|
||||
let next_lo = if let Some(last) = self.blocks.last() {
|
||||
let next_lo = if let Some(last) = self.blocks.last_index() {
|
||||
self.blocks[last].terminator().source_info.span.hi()
|
||||
} else {
|
||||
BytePos(1)
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Code shared by trait and projection goals for candidate assembly.
|
||||
|
||||
use super::search_graph::OverflowHandler;
|
||||
#[cfg(doc)]
|
||||
use super::trait_goals::structural_traits::*;
|
||||
use super::{EvalCtxt, SolverMode};
|
||||
@ -279,25 +280,38 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
return
|
||||
};
|
||||
|
||||
self.probe(|ecx| {
|
||||
let normalized_ty = ecx.next_ty_infer();
|
||||
let normalizes_to_goal = goal.with(
|
||||
tcx,
|
||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: normalized_ty.into(),
|
||||
}),
|
||||
);
|
||||
ecx.add_goal(normalizes_to_goal);
|
||||
if let Ok(_) = ecx.try_evaluate_added_goals() {
|
||||
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
|
||||
|
||||
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
|
||||
// This doesn't work as long as we use `CandidateSource` in winnowing.
|
||||
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
|
||||
candidates.extend(ecx.assemble_and_evaluate_candidates(goal));
|
||||
}
|
||||
let normalized_self_candidates: Result<_, NoSolution> = self.probe(|ecx| {
|
||||
ecx.with_incremented_depth(
|
||||
|ecx| {
|
||||
let result = ecx.evaluate_added_goals_and_make_canonical_response(
|
||||
Certainty::Maybe(MaybeCause::Overflow),
|
||||
)?;
|
||||
Ok(vec![Candidate { source: CandidateSource::BuiltinImpl, result }])
|
||||
},
|
||||
|ecx| {
|
||||
let normalized_ty = ecx.next_ty_infer();
|
||||
let normalizes_to_goal = goal.with(
|
||||
tcx,
|
||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: normalized_ty.into(),
|
||||
}),
|
||||
);
|
||||
ecx.add_goal(normalizes_to_goal);
|
||||
let _ = ecx.try_evaluate_added_goals()?;
|
||||
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
|
||||
// NOTE: Alternatively we could call `evaluate_goal` here and only
|
||||
// have a `Normalized` candidate. This doesn't work as long as we
|
||||
// use `CandidateSource` in winnowing.
|
||||
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
|
||||
Ok(ecx.assemble_and_evaluate_candidates(goal))
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
if let Ok(normalized_self_candidates) = normalized_self_candidates {
|
||||
candidates.extend(normalized_self_candidates);
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_impl_candidates<G: GoalKind<'tcx>>(
|
||||
|
@ -70,7 +70,7 @@ impl<'tcx> SearchGraph<'tcx> {
|
||||
/// Whether we're currently in a cycle. This should only be used
|
||||
/// for debug assertions.
|
||||
pub(super) fn in_cycle(&self) -> bool {
|
||||
if let Some(stack_depth) = self.stack.last() {
|
||||
if let Some(stack_depth) = self.stack.last_index() {
|
||||
// Either the current goal on the stack is the root of a cycle...
|
||||
if self.stack[stack_depth].has_been_used {
|
||||
return true;
|
||||
|
@ -73,6 +73,27 @@ pub(in crate::solve) trait OverflowHandler<'tcx> {
|
||||
self.search_graph().overflow_data.deal_with_overflow();
|
||||
on_overflow(self)
|
||||
}
|
||||
|
||||
// Increment the `additional_depth` by one and evaluate `body`, or `on_overflow`
|
||||
// if the depth is overflown.
|
||||
fn with_incremented_depth<T>(
|
||||
&mut self,
|
||||
on_overflow: impl FnOnce(&mut Self) -> T,
|
||||
body: impl FnOnce(&mut Self) -> T,
|
||||
) -> T {
|
||||
let depth = self.search_graph().stack.len();
|
||||
self.search_graph().overflow_data.additional_depth += 1;
|
||||
|
||||
let result = if self.search_graph().overflow_data.has_overflow(depth) {
|
||||
self.search_graph().overflow_data.deal_with_overflow();
|
||||
on_overflow(self)
|
||||
} else {
|
||||
body(self)
|
||||
};
|
||||
|
||||
self.search_graph().overflow_data.additional_depth -= 1;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx> {
|
||||
|
@ -31,7 +31,6 @@ use rustc_span::hygiene::{AstPass, MacroKind};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{self, ExpnKind};
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::BTreeMap;
|
||||
@ -270,15 +269,7 @@ fn clean_where_predicate<'tcx>(
|
||||
let bound_params = wbp
|
||||
.bound_generic_params
|
||||
.iter()
|
||||
.map(|param| {
|
||||
// Higher-ranked params must be lifetimes.
|
||||
// Higher-ranked lifetimes can't have bounds.
|
||||
assert_matches!(
|
||||
param,
|
||||
hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
|
||||
);
|
||||
Lifetime(param.name.ident().name)
|
||||
})
|
||||
.map(|param| clean_generic_param(cx, None, param))
|
||||
.collect();
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: clean_ty(wbp.bounded_ty, cx),
|
||||
@ -410,7 +401,7 @@ fn clean_projection_predicate<'tcx>(
|
||||
.collect_referenced_late_bound_regions(&pred)
|
||||
.into_iter()
|
||||
.filter_map(|br| match br {
|
||||
ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)),
|
||||
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
@ -508,7 +499,6 @@ fn clean_generic_param_def<'tcx>(
|
||||
ty::GenericParamDefKind::Const { has_default } => (
|
||||
def.name,
|
||||
GenericParamDefKind::Const {
|
||||
did: def.def_id,
|
||||
ty: Box::new(clean_middle_ty(
|
||||
ty::Binder::dummy(
|
||||
cx.tcx
|
||||
@ -578,7 +568,6 @@ fn clean_generic_param<'tcx>(
|
||||
hir::GenericParamKind::Const { ty, default } => (
|
||||
param.name.ident().name,
|
||||
GenericParamDefKind::Const {
|
||||
did: param.def_id.to_def_id(),
|
||||
ty: Box::new(clean_ty(ty, cx)),
|
||||
default: default
|
||||
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
||||
@ -831,7 +820,7 @@ fn clean_ty_generics<'tcx>(
|
||||
p.get_bound_params()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|param| GenericParamDef::lifetime(param.0))
|
||||
.cloned()
|
||||
.collect(),
|
||||
));
|
||||
}
|
||||
|
@ -49,11 +49,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
|
||||
equalities.retain(|(lhs, rhs, bound_params)| {
|
||||
let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
|
||||
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
|
||||
let bound_params = bound_params
|
||||
.into_iter()
|
||||
.map(|param| clean::GenericParamDef::lifetime(param.0))
|
||||
.collect();
|
||||
merge_bounds(cx, bounds, bound_params, trait_did, name, rhs)
|
||||
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
|
||||
});
|
||||
|
||||
// And finally, let's reassemble everything
|
||||
|
@ -232,14 +232,6 @@ impl ExternalCrate {
|
||||
hir::ItemKind::Mod(_) => {
|
||||
as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
|
||||
}
|
||||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||
if tcx.visibility(id.owner_id).is_public() =>
|
||||
{
|
||||
path.res
|
||||
.iter()
|
||||
.find_map(|res| as_keyword(res.expect_non_local()))
|
||||
.map(|(_, prim)| (id.owner_id.to_def_id(), prim))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
@ -302,15 +294,6 @@ impl ExternalCrate {
|
||||
hir::ItemKind::Mod(_) => {
|
||||
as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
|
||||
}
|
||||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||
if tcx.visibility(id.owner_id).is_public() =>
|
||||
{
|
||||
path.res
|
||||
.iter()
|
||||
.find_map(|res| as_primitive(res.expect_non_local()))
|
||||
// Pretend the primitive is local.
|
||||
.map(|(_, prim)| (id.owner_id.to_def_id(), prim))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
@ -1236,9 +1219,9 @@ impl Lifetime {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum WherePredicate {
|
||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
|
||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
|
||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
|
||||
EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<Lifetime> },
|
||||
EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<GenericParamDef> },
|
||||
}
|
||||
|
||||
impl WherePredicate {
|
||||
@ -1250,7 +1233,7 @@ impl WherePredicate {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
|
||||
pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
|
||||
match self {
|
||||
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
|
||||
Some(bound_params)
|
||||
@ -1264,7 +1247,7 @@ impl WherePredicate {
|
||||
pub(crate) enum GenericParamDefKind {
|
||||
Lifetime { outlives: Vec<Lifetime> },
|
||||
Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
|
||||
Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
|
||||
Const { ty: Box<Type>, default: Option<Box<String>> },
|
||||
}
|
||||
|
||||
impl GenericParamDefKind {
|
||||
|
@ -307,13 +307,13 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
write!(
|
||||
f,
|
||||
"for<{:#}> {ty_cx:#}: {generic_bounds:#}",
|
||||
comma_sep(bound_params.iter().map(|lt| lt.print()), true)
|
||||
comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"for<{}> {ty_cx}: {generic_bounds}",
|
||||
comma_sep(bound_params.iter().map(|lt| lt.print()), true)
|
||||
comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
|
||||
default: default.map(|x| (*x).into_tcx(tcx)),
|
||||
synthetic,
|
||||
},
|
||||
Const { did: _, ty, default } => GenericParamDefKind::Const {
|
||||
Const { ty, default } => GenericParamDefKind::Const {
|
||||
type_: (*ty).into_tcx(tcx),
|
||||
default: default.map(|x| *x),
|
||||
},
|
||||
@ -473,9 +473,35 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
||||
bounds: bounds.into_tcx(tcx),
|
||||
generic_params: bound_params
|
||||
.into_iter()
|
||||
.map(|x| GenericParamDef {
|
||||
name: x.0.to_string(),
|
||||
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
|
||||
.map(|x| {
|
||||
let name = x.name.to_string();
|
||||
let kind = match x.kind {
|
||||
clean::GenericParamDefKind::Lifetime { outlives } => {
|
||||
GenericParamDefKind::Lifetime {
|
||||
outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(),
|
||||
}
|
||||
}
|
||||
clean::GenericParamDefKind::Type {
|
||||
did: _,
|
||||
bounds,
|
||||
default,
|
||||
synthetic,
|
||||
} => GenericParamDefKind::Type {
|
||||
bounds: bounds
|
||||
.into_iter()
|
||||
.map(|bound| bound.into_tcx(tcx))
|
||||
.collect(),
|
||||
default: default.map(|ty| (*ty).into_tcx(tcx)),
|
||||
synthetic,
|
||||
},
|
||||
clean::GenericParamDefKind::Const { ty, default } => {
|
||||
GenericParamDefKind::Const {
|
||||
type_: (*ty).into_tcx(tcx),
|
||||
default: default.map(|d| *d),
|
||||
}
|
||||
}
|
||||
};
|
||||
GenericParamDef { name, kind }
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
|
@ -19,12 +19,12 @@
|
||||
let mut _17: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
let _18: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
let _19: [core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
let mut _27: bool; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
|
||||
let mut _28: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
|
||||
let mut _29: isize; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
|
||||
@ -108,34 +108,34 @@
|
||||
StorageLive(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
StorageLive(_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
StorageLive(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
StorageLive(_20); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
StorageLive(_21); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
_22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
_21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
_20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
StorageLive(_20); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
StorageLive(_21); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
_22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
_21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
_20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||
// mir::Constant
|
||||
// + span: $DIR/lifetimes.rs:27:21: 27:22
|
||||
// + span: $DIR/lifetimes.rs:27:20: 27:23
|
||||
// + user_ty: UserType(4)
|
||||
// + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_21); // scope 4 at $DIR/lifetimes.rs:+10:21: +10:22
|
||||
StorageLive(_23); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
StorageLive(_24); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
_25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
_24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
_23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
StorageDead(_21); // scope 4 at $DIR/lifetimes.rs:+10:22: +10:23
|
||||
StorageLive(_23); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
StorageLive(_24); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
_25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
_24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
_23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||
// mir::Constant
|
||||
// + span: $DIR/lifetimes.rs:27:25: 27:26
|
||||
// + span: $DIR/lifetimes.rs:27:24: 27:27
|
||||
// + user_ty: UserType(5)
|
||||
// + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<u32>}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_24); // scope 4 at $DIR/lifetimes.rs:+10:25: +10:26
|
||||
StorageDead(_24); // scope 4 at $DIR/lifetimes.rs:+10:26: +10:27
|
||||
_19 = [move _20, move _23]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
StorageDead(_23); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||
|
24
tests/rustdoc-json/non_lifetime_binders.rs
Normal file
24
tests/rustdoc-json/non_lifetime_binders.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(non_lifetime_binders)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![no_core]
|
||||
#![feature(lang_items, no_core)]
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
pub trait Trait {}
|
||||
|
||||
#[lang = "phantom_data"]
|
||||
struct PhantomData<T_>;
|
||||
|
||||
pub struct Wrapper<T_>(PhantomData<T_>);
|
||||
|
||||
// @count "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
|
||||
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
|
||||
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
|
||||
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
|
||||
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
|
||||
pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}
|
@ -6,7 +6,7 @@ extern crate issue_15318;
|
||||
|
||||
pub use issue_15318::ptr;
|
||||
|
||||
// @has issue_15318_2/fn.bar.html \
|
||||
// @!has issue_15318_2/fn.bar.html \
|
||||
// '//*[@href="primitive.pointer.html"]' \
|
||||
// '*mut T'
|
||||
pub fn bar<T>(ptr: *mut T) {}
|
||||
|
9
tests/rustdoc/non_lifetime_binders.rs
Normal file
9
tests/rustdoc/non_lifetime_binders.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![feature(non_lifetime_binders)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait Trait {}
|
||||
|
||||
pub struct Wrapper<T: ?Sized>(Box<T>);
|
||||
|
||||
// @has non_lifetime_binders/fn.foo.html '//pre' "fn foo()where for<'a, T> &'a Wrapper<T>: Trait"
|
||||
pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}
|
@ -1,8 +1,8 @@
|
||||
error[E0015]: cannot call non-const formatting macro in constant functions
|
||||
--> $DIR/format.rs:2:20
|
||||
--> $DIR/format.rs:2:13
|
||||
|
|
||||
LL | panic!("{:?}", 0);
|
||||
| ^
|
||||
| ^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
= note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@ -17,10 +17,10 @@ LL | panic!("{:?}", 0);
|
||||
= note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0015]: cannot call non-const formatting macro in constant functions
|
||||
--> $DIR/format.rs:8:22
|
||||
--> $DIR/format.rs:8:15
|
||||
|
|
||||
LL | println!("{:?}", 0);
|
||||
| ^
|
||||
| ^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
22
tests/ui/fmt/format-args-argument-span.rs
Normal file
22
tests/ui/fmt/format-args-argument-span.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// check-compile
|
||||
|
||||
struct DisplayOnly;
|
||||
|
||||
impl std::fmt::Display for DisplayOnly {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Some(1);
|
||||
println!("{x:?} {x} {x:?}");
|
||||
//~^ ERROR: `Option<{integer}>` doesn't implement `std::fmt::Display`
|
||||
println!("{x:?} {x} {x:?}", x = Some(1));
|
||||
//~^ ERROR: `Option<{integer}>` doesn't implement `std::fmt::Display`
|
||||
let x = DisplayOnly;
|
||||
println!("{x} {x:?} {x}");
|
||||
//~^ ERROR: `DisplayOnly` doesn't implement `Debug`
|
||||
println!("{x} {x:?} {x}", x = DisplayOnly);
|
||||
//~^ ERROR: `DisplayOnly` doesn't implement `Debug`
|
||||
}
|
51
tests/ui/fmt/format-args-argument-span.stderr
Normal file
51
tests/ui/fmt/format-args-argument-span.stderr
Normal file
@ -0,0 +1,51 @@
|
||||
error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/format-args-argument-span.rs:13:21
|
||||
|
|
||||
LL | println!("{x:?} {x} {x:?}");
|
||||
| ^^^ `Option<{integer}>` cannot be formatted with the default formatter
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/format-args-argument-span.rs:15:37
|
||||
|
|
||||
LL | println!("{x:?} {x} {x:?}", x = Some(1));
|
||||
| ^^^^^^^ `Option<{integer}>` cannot be formatted with the default formatter
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: `DisplayOnly` doesn't implement `Debug`
|
||||
--> $DIR/format-args-argument-span.rs:18:19
|
||||
|
|
||||
LL | println!("{x} {x:?} {x}");
|
||||
| ^^^^^ `DisplayOnly` cannot be formatted using `{:?}`
|
||||
|
|
||||
= help: the trait `Debug` is not implemented for `DisplayOnly`
|
||||
= note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly`
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider annotating `DisplayOnly` with `#[derive(Debug)]`
|
||||
|
|
||||
LL | #[derive(Debug)]
|
||||
|
|
||||
|
||||
error[E0277]: `DisplayOnly` doesn't implement `Debug`
|
||||
--> $DIR/format-args-argument-span.rs:20:35
|
||||
|
|
||||
LL | println!("{x} {x:?} {x}", x = DisplayOnly);
|
||||
| ^^^^^^^^^^^ `DisplayOnly` cannot be formatted using `{:?}`
|
||||
|
|
||||
= help: the trait `Debug` is not implemented for `DisplayOnly`
|
||||
= note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly`
|
||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider annotating `DisplayOnly` with `#[derive(Debug)]`
|
||||
|
|
||||
LL | #[derive(Debug)]
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -300,10 +300,9 @@ error[E0308]: mismatched types
|
||||
--> $DIR/ifmt-bad-arg.rs:78:32
|
||||
|
|
||||
LL | println!("{} {:.*} {}", 1, 3.2, 4);
|
||||
| ^^^
|
||||
| |
|
||||
| expected `&usize`, found `&{float}`
|
||||
| arguments to this function are incorrect
|
||||
| -- ^^^ expected `&usize`, found `&{float}`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&usize`
|
||||
found reference `&{float}`
|
||||
@ -315,10 +314,9 @@ error[E0308]: mismatched types
|
||||
--> $DIR/ifmt-bad-arg.rs:81:35
|
||||
|
|
||||
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
|
||||
| ^^^
|
||||
| |
|
||||
| expected `&usize`, found `&{float}`
|
||||
| arguments to this function are incorrect
|
||||
| -- ^^^ expected `&usize`, found `&{float}`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&usize`
|
||||
found reference `&{float}`
|
||||
|
@ -2,7 +2,9 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied
|
||||
--> $DIR/ifmt-unimpl.rs:2:21
|
||||
|
|
||||
LL | format!("{:X}", "3");
|
||||
| ^^^ the trait `UpperHex` is not implemented for `str`
|
||||
| ---- ^^^ the trait `UpperHex` is not implemented for `str`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `UpperHex`:
|
||||
&T
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: `<impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/issue-97760.rs:4:20
|
||||
--> $DIR/issue-97760.rs:4:19
|
||||
|
|
||||
LL | println!("{x}");
|
||||
| ^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter
|
||||
| ^^^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `<impl IntoIterator as IntoIterator>::Item`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
|
19
tests/ui/traits/new-solver/recursive-self-normalization-2.rs
Normal file
19
tests/ui/traits/new-solver/recursive-self-normalization-2.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Foo1 {
|
||||
type Assoc1;
|
||||
}
|
||||
|
||||
trait Foo2 {
|
||||
type Assoc2;
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
|
||||
needs_bar::<T::Assoc1>();
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
15
tests/ui/traits/new-solver/recursive-self-normalization.rs
Normal file
15
tests/ui/traits/new-solver/recursive-self-normalization.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Foo {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
|
||||
needs_bar::<T::Assoc>();
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-self-normalization.rs:11:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
Loading…
Reference in New Issue
Block a user