Auto merge of #116408 - matthiaskrgr:rollup-hmolg4m, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #115961 (Replace 'mutex' with 'lock' in RwLock documentation) - #116146 (Clarify `arg` and `args` documentation) - #116363 (Adapt `todo!` documentation to mention displaying custom values) - #116365 (bootstrap: make copying linker binaries conditional) - #116388 (rustdoc: fix & clean up handling of cross-crate higher-ranked parameters) - #116393 (Emit feature gate *warning* for `auto` traits pre-expansion) - #116395 (Mark myself as vacation or whatever) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a7bb2f67bf
@ -603,6 +603,7 @@ macro_rules! gate_all_legacy_dont_use {
|
||||
"exclusive range pattern syntax is experimental"
|
||||
);
|
||||
gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
@ -813,7 +813,12 @@ fn check_auto_or_unsafe_trait_item(&mut self) -> bool {
|
||||
fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
|
||||
let unsafety = self.parse_unsafety(Case::Sensitive);
|
||||
// Parse optional `auto` prefix.
|
||||
let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
|
||||
let is_auto = if self.eat_keyword(kw::Auto) {
|
||||
self.sess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
|
||||
IsAuto::Yes
|
||||
} else {
|
||||
IsAuto::No
|
||||
};
|
||||
|
||||
self.expect_keyword(kw::Trait)?;
|
||||
let ident = self.parse_ident()?;
|
||||
|
@ -719,7 +719,8 @@ macro_rules! unreachable {
|
||||
/// The difference between `unimplemented!` and [`todo!`] is that while `todo!`
|
||||
/// conveys an intent of implementing the functionality later and the message is "not yet
|
||||
/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
|
||||
/// Also some IDEs will mark `todo!`s.
|
||||
///
|
||||
/// Also, some IDEs will mark `todo!`s.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -805,11 +806,15 @@ macro_rules! unimplemented {
|
||||
/// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys
|
||||
/// an intent of implementing the functionality later and the message is "not yet
|
||||
/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
|
||||
/// Also some IDEs will mark `todo!`s.
|
||||
///
|
||||
/// Also, some IDEs will mark `todo!`s.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This will always [`panic!`].
|
||||
/// This will always [`panic!`] because `todo!` is just a shorthand for `panic!` with a
|
||||
/// fixed, specific message.
|
||||
///
|
||||
/// Like `panic!`, this macro has a second form for displaying custom values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -817,38 +822,47 @@ macro_rules! unimplemented {
|
||||
///
|
||||
/// ```
|
||||
/// trait Foo {
|
||||
/// fn bar(&self);
|
||||
/// fn bar(&self) -> u8;
|
||||
/// fn baz(&self);
|
||||
/// fn qux(&self) -> Result<u64, ()>;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// We want to implement `Foo` on one of our types, but we also want to work on
|
||||
/// just `bar()` first. In order for our code to compile, we need to implement
|
||||
/// `baz()`, so we can use `todo!`:
|
||||
/// `baz()` and `qux()`, so we can use `todo!`:
|
||||
///
|
||||
/// ```
|
||||
/// # trait Foo {
|
||||
/// # fn bar(&self);
|
||||
/// # fn bar(&self) -> u8;
|
||||
/// # fn baz(&self);
|
||||
/// # fn qux(&self) -> Result<u64, ()>;
|
||||
/// # }
|
||||
/// struct MyStruct;
|
||||
///
|
||||
/// impl Foo for MyStruct {
|
||||
/// fn bar(&self) {
|
||||
/// // implementation goes here
|
||||
/// fn bar(&self) -> u8 {
|
||||
/// 1 + 1
|
||||
/// }
|
||||
///
|
||||
/// fn baz(&self) {
|
||||
/// // let's not worry about implementing baz() for now
|
||||
/// // Let's not worry about implementing baz() for now
|
||||
/// todo!();
|
||||
/// }
|
||||
///
|
||||
/// fn qux(&self) -> Result<u64, ()> {
|
||||
/// // We can add a message to todo! to display our omission.
|
||||
/// // This will display:
|
||||
/// // "thread 'main' panicked at 'not yet implemented: MyStruct is not yet quxable'".
|
||||
/// todo!("MyStruct is not yet quxable");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let s = MyStruct;
|
||||
/// s.bar();
|
||||
///
|
||||
/// // we aren't even using baz(), so this is fine.
|
||||
/// // We aren't even using baz() or qux(), so this is fine.
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
|
@ -607,7 +607,7 @@ pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
|
||||
///
|
||||
/// Note that the argument is not passed through a shell, but given
|
||||
/// literally to the program. This means that shell syntax like quotes,
|
||||
/// escaped characters, word splitting, glob patterns, substitution, etc.
|
||||
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
|
||||
/// have no effect.
|
||||
///
|
||||
/// # Examples
|
||||
@ -637,7 +637,7 @@ pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
|
||||
///
|
||||
/// Note that the arguments are not passed through a shell, but given
|
||||
/// literally to the program. This means that shell syntax like quotes,
|
||||
/// escaped characters, word splitting, glob patterns, substitution, etc.
|
||||
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
|
||||
/// have no effect.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -380,7 +380,7 @@ pub fn is_poisoned(&self) -> bool {
|
||||
///
|
||||
/// If the lock is poisoned, it will remain poisoned until this function is called. This allows
|
||||
/// recovering from a poisoned state and marking that it has recovered. For example, if the
|
||||
/// value is overwritten by a known-good value, then the mutex can be marked as un-poisoned. Or
|
||||
/// value is overwritten by a known-good value, then the lock can be marked as un-poisoned. Or
|
||||
/// possibly, the value could be inspected to determine if it is in a consistent state, and if
|
||||
/// so the poison is removed.
|
||||
///
|
||||
@ -397,7 +397,7 @@ pub fn is_poisoned(&self) -> bool {
|
||||
///
|
||||
/// let _ = thread::spawn(move || {
|
||||
/// let _lock = c_lock.write().unwrap();
|
||||
/// panic!(); // the mutex gets poisoned
|
||||
/// panic!(); // the lock gets poisoned
|
||||
/// }).join();
|
||||
///
|
||||
/// assert_eq!(lock.is_poisoned(), true);
|
||||
|
@ -167,12 +167,14 @@ fn run(self, builder: &Builder<'_>) {
|
||||
.rustc_snapshot_sysroot()
|
||||
.join("lib")
|
||||
.join("rustlib")
|
||||
.join(&compiler.host.triple)
|
||||
.join(compiler.host.triple)
|
||||
.join("bin");
|
||||
let target_sysroot_bin =
|
||||
builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin");
|
||||
t!(fs::create_dir_all(&target_sysroot_bin));
|
||||
builder.cp_r(&src_sysroot_bin, &target_sysroot_bin);
|
||||
if src_sysroot_bin.exists() {
|
||||
let target_sysroot_bin =
|
||||
builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin");
|
||||
t!(fs::create_dir_all(&target_sysroot_bin));
|
||||
builder.cp_r(&src_sysroot_bin, &target_sysroot_bin);
|
||||
}
|
||||
}
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
|
||||
|
@ -551,8 +551,8 @@ fn param_env_to_generics(
|
||||
WherePredicate::RegionPredicate { lifetime, bounds } => {
|
||||
lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
|
||||
}
|
||||
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
|
||||
match *lhs {
|
||||
WherePredicate::EqPredicate { lhs, rhs } => {
|
||||
match lhs {
|
||||
Type::QPath(box QPathData {
|
||||
ref assoc,
|
||||
ref self_type,
|
||||
@ -590,14 +590,13 @@ fn param_env_to_generics(
|
||||
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
||||
bindings.push(TypeBinding {
|
||||
assoc: assoc.clone(),
|
||||
kind: TypeBindingKind::Equality { term: *rhs },
|
||||
kind: TypeBindingKind::Equality { term: rhs },
|
||||
});
|
||||
}
|
||||
GenericArgs::Parenthesized { .. } => {
|
||||
existing_predicates.push(WherePredicate::EqPredicate {
|
||||
lhs: lhs.clone(),
|
||||
rhs,
|
||||
bound_params,
|
||||
});
|
||||
continue; // If something other than a Fn ends up
|
||||
// with parentheses, leave it alone
|
||||
|
@ -18,9 +18,9 @@
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
|
||||
use crate::clean::{
|
||||
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
|
||||
clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
|
||||
clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
|
||||
self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item,
|
||||
clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings,
|
||||
clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
|
||||
AttributesExt, ImplKind, ItemId, Type,
|
||||
};
|
||||
use crate::core::DocContext;
|
||||
@ -239,20 +239,13 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
|
||||
|
||||
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
|
||||
let sig = cx.tcx.fn_sig(did).instantiate_identity();
|
||||
|
||||
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
|
||||
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
|
||||
Some(clean::GenericParamDef::lifetime(name))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let predicates = cx.tcx.explicit_predicates_of(did);
|
||||
|
||||
let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
|
||||
// NOTE: generics need to be cleaned before the decl!
|
||||
let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
|
||||
// FIXME: This does not place parameters in source order (late-bound ones come last)
|
||||
generics.params.extend(late_bound_regions);
|
||||
generics.params.extend(clean_bound_vars(sig.bound_vars()));
|
||||
let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
|
||||
(generics, decl)
|
||||
});
|
||||
|
@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
bindings: ThinVec<TypeBinding>,
|
||||
) -> GenericBound {
|
||||
// collect any late bound regions
|
||||
let late_bound_regions: Vec<_> = cx
|
||||
.tcx
|
||||
.collect_referenced_late_bound_regions(&poly_trait_ref)
|
||||
.into_iter()
|
||||
.filter_map(|br| match br {
|
||||
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
|
||||
GenericBound::TraitBound(
|
||||
PolyTrait { trait_, generic_params: late_bound_regions },
|
||||
PolyTrait {
|
||||
trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings),
|
||||
generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
|
||||
},
|
||||
hir::TraitBoundModifier::None,
|
||||
)
|
||||
}
|
||||
@ -338,9 +329,8 @@ fn clean_where_predicate<'tcx>(
|
||||
},
|
||||
|
||||
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
||||
lhs: Box::new(clean_ty(wrp.lhs_ty, cx)),
|
||||
rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()),
|
||||
bound_params: Vec::new(),
|
||||
lhs: clean_ty(wrp.lhs_ty, cx),
|
||||
rhs: clean_ty(wrp.rhs_ty, cx).into(),
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -436,20 +426,9 @@ fn clean_projection_predicate<'tcx>(
|
||||
pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
|
||||
cx: &mut DocContext<'tcx>,
|
||||
) -> WherePredicate {
|
||||
let late_bound_regions = cx
|
||||
.tcx
|
||||
.collect_referenced_late_bound_regions(&pred)
|
||||
.into_iter()
|
||||
.filter_map(|br| match br {
|
||||
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
WherePredicate::EqPredicate {
|
||||
lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
|
||||
rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
|
||||
bound_params: late_bound_regions,
|
||||
lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None),
|
||||
rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,8 +682,8 @@ pub(crate) fn clean_generics<'tcx>(
|
||||
}
|
||||
}
|
||||
}
|
||||
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
|
||||
eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params });
|
||||
WherePredicate::EqPredicate { lhs, rhs } => {
|
||||
eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -798,11 +777,9 @@ fn clean_ty_generics<'tcx>(
|
||||
})
|
||||
.collect::<ThinVec<GenericParamDef>>();
|
||||
|
||||
// param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)]
|
||||
let mut impl_trait_proj = FxHashMap::<
|
||||
u32,
|
||||
Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec<GenericParamDef>)>,
|
||||
>::default();
|
||||
// param index -> [(trait DefId, associated type name & generics, term)]
|
||||
let mut impl_trait_proj =
|
||||
FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
|
||||
|
||||
let where_predicates = preds
|
||||
.predicates
|
||||
@ -854,11 +831,6 @@ fn clean_ty_generics<'tcx>(
|
||||
trait_did,
|
||||
name,
|
||||
proj.map_bound(|p| p.term),
|
||||
pred.get_bound_params()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect(),
|
||||
));
|
||||
}
|
||||
|
||||
@ -894,9 +866,9 @@ fn clean_ty_generics<'tcx>(
|
||||
|
||||
let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
|
||||
if let Some(proj) = impl_trait_proj.remove(&idx) {
|
||||
for (trait_did, name, rhs, bound_params) in proj {
|
||||
for (trait_did, name, rhs) in proj {
|
||||
let rhs = clean_middle_term(rhs, cx);
|
||||
simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs);
|
||||
simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,23 +1335,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity();
|
||||
|
||||
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
|
||||
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
|
||||
if name != kw::UnderscoreLifetime =>
|
||||
{
|
||||
Some(GenericParamDef::lifetime(name))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let mut generics = clean_ty_generics(
|
||||
cx,
|
||||
tcx.generics_of(assoc_item.def_id),
|
||||
tcx.explicit_predicates_of(assoc_item.def_id),
|
||||
);
|
||||
// FIXME: This does not place parameters in source order (late-bound ones come last)
|
||||
generics.params.extend(late_bound_regions);
|
||||
generics.params.extend(clean_bound_vars(sig.bound_vars()));
|
||||
|
||||
let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
|
||||
|
||||
@ -2115,9 +2077,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
// FIXME: should we merge the outer and inner binders somehow?
|
||||
let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
|
||||
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
|
||||
let generic_params = clean_bound_vars(sig.bound_vars());
|
||||
|
||||
BareFunction(Box::new(BareFunctionDecl {
|
||||
unsafety: sig.unsafety(),
|
||||
generic_params: Vec::new(),
|
||||
generic_params,
|
||||
decl,
|
||||
abi: sig.abi(),
|
||||
}))
|
||||
@ -2193,8 +2157,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
|
||||
let late_bound_regions: FxIndexSet<_> = obj
|
||||
.iter()
|
||||
.flat_map(|pb| pb.bound_vars())
|
||||
.filter_map(|br| match br {
|
||||
.flat_map(|pred| pred.bound_vars())
|
||||
.filter_map(|var| match var {
|
||||
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
|
||||
if name != kw::UnderscoreLifetime =>
|
||||
{
|
||||
@ -2268,6 +2232,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
ty::Bound(_, ref ty) => match ty.kind {
|
||||
ty::BoundTyKind::Param(_, name) => Generic(name),
|
||||
ty::BoundTyKind::Anon => panic!("unexpected anonymous bound type variable"),
|
||||
},
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
||||
// If it's already in the same alias, don't get an infinite loop.
|
||||
if cx.current_type_aliases.contains_key(&def_id) {
|
||||
@ -2296,7 +2265,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
|
||||
ty::Closure(..) => panic!("Closure"),
|
||||
ty::Generator(..) => panic!("Generator"),
|
||||
ty::Bound(..) => panic!("Bound"),
|
||||
ty::Placeholder(..) => panic!("Placeholder"),
|
||||
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
|
||||
ty::Infer(..) => panic!("Infer"),
|
||||
@ -3127,3 +3095,30 @@ fn clean_type_binding<'tcx>(
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_bound_vars<'tcx>(
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
) -> Vec<GenericParamDef> {
|
||||
bound_vars
|
||||
.into_iter()
|
||||
.filter_map(|var| match var {
|
||||
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
|
||||
if name != kw::UnderscoreLifetime =>
|
||||
{
|
||||
Some(GenericParamDef::lifetime(name))
|
||||
}
|
||||
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(did, name)) => Some(GenericParamDef {
|
||||
name,
|
||||
kind: GenericParamDefKind::Type {
|
||||
did,
|
||||
bounds: Vec::new(),
|
||||
default: None,
|
||||
synthetic: false,
|
||||
},
|
||||
}),
|
||||
// FIXME(non_lifetime_binders): Support higher-ranked const parameters.
|
||||
ty::BoundVariableKind::Const => None,
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
|
||||
WP::RegionPredicate { lifetime, bounds } => {
|
||||
lifetimes.push((lifetime, bounds));
|
||||
}
|
||||
WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)),
|
||||
WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
|
||||
}
|
||||
}
|
||||
|
||||
// Look for equality predicates on associated types that can be merged into
|
||||
// general bound predicates.
|
||||
equalities.retain(|(lhs, rhs, bound_params)| {
|
||||
equalities.retain(|(lhs, rhs)| {
|
||||
let Some((ty, trait_did, name)) = lhs.projection() else {
|
||||
return true;
|
||||
};
|
||||
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
|
||||
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
|
||||
merge_bounds(cx, bounds, trait_did, name, rhs)
|
||||
});
|
||||
|
||||
// And finally, let's reassemble everything
|
||||
@ -64,18 +64,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
|
||||
bounds,
|
||||
bound_params,
|
||||
}));
|
||||
clauses.extend(equalities.into_iter().map(|(lhs, rhs, bound_params)| WP::EqPredicate {
|
||||
lhs,
|
||||
rhs,
|
||||
bound_params,
|
||||
}));
|
||||
clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
|
||||
clauses
|
||||
}
|
||||
|
||||
pub(crate) fn merge_bounds(
|
||||
cx: &clean::DocContext<'_>,
|
||||
bounds: &mut Vec<clean::GenericBound>,
|
||||
mut bound_params: Vec<clean::GenericParamDef>,
|
||||
trait_did: DefId,
|
||||
assoc: clean::PathSegment,
|
||||
rhs: &clean::Term,
|
||||
@ -93,12 +88,6 @@ pub(crate) fn merge_bounds(
|
||||
}
|
||||
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
|
||||
|
||||
trait_ref.generic_params.append(&mut bound_params);
|
||||
// Sort parameters (likely) originating from a hashset alphabetically to
|
||||
// produce predictable output (and to allow for full deduplication).
|
||||
trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
|
||||
trait_ref.generic_params.dedup_by_key(|p| p.name);
|
||||
|
||||
match last.args {
|
||||
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||
bindings.push(clean::TypeBinding {
|
||||
|
@ -1289,7 +1289,7 @@ pub(crate) fn elided() -> Lifetime {
|
||||
pub(crate) enum WherePredicate {
|
||||
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<GenericParamDef> },
|
||||
EqPredicate { lhs: Type, rhs: Term },
|
||||
}
|
||||
|
||||
impl WherePredicate {
|
||||
@ -1300,15 +1300,6 @@ pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
|
||||
match self {
|
||||
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
|
||||
Some(bound_params)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
|
@ -326,8 +326,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
bounds_display.truncate(bounds_display.len() - " + ".len());
|
||||
write!(f, "{}: {bounds_display}", lifetime.print())
|
||||
}
|
||||
// FIXME(fmease): Render bound params.
|
||||
clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
|
||||
clean::WherePredicate::EqPredicate { lhs, rhs } => {
|
||||
if f.alternate() {
|
||||
write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
|
||||
} else {
|
||||
|
@ -506,9 +506,8 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
|
||||
lifetime: convert_lifetime(lifetime),
|
||||
bounds: bounds.into_tcx(tcx),
|
||||
},
|
||||
// FIXME(fmease): Convert bound parameters as well.
|
||||
EqPredicate { lhs, rhs, bound_params: _ } => {
|
||||
WherePredicate::EqPredicate { lhs: (*lhs).into_tcx(tcx), rhs: (*rhs).into_tcx(tcx) }
|
||||
EqPredicate { lhs, rhs } => {
|
||||
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
tests/rustdoc/inline_cross/auxiliary/fn-type.rs
Normal file
1
tests/rustdoc/inline_cross/auxiliary/fn-type.rs
Normal file
@ -0,0 +1 @@
|
||||
pub type F = for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();
|
@ -15,7 +15,7 @@ pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
|
||||
|
||||
pub fn func5(
|
||||
_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,
|
||||
_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
|
||||
_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
|
||||
) {}
|
||||
|
||||
pub trait Other {
|
||||
|
10
tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs
Normal file
10
tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![feature(non_lifetime_binders)]
|
||||
|
||||
pub trait Trait<T> {}
|
||||
|
||||
pub fn f(_: impl for<T> Trait<T>) {}
|
||||
|
||||
pub fn g<T>(_: T)
|
||||
where
|
||||
T: for<U> Trait<U>,
|
||||
{}
|
12
tests/rustdoc/inline_cross/fn-type.rs
Normal file
12
tests/rustdoc/inline_cross/fn-type.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// Make sure that we print the higher-ranked parameters of cross-crate function pointer types.
|
||||
// They should be rendered exactly as the user wrote it, i.e., in source order and with unused
|
||||
// parameters present, not stripped.
|
||||
|
||||
// aux-crate:fn_type=fn-type.rs
|
||||
// edition: 2021
|
||||
#![crate_name = "user"]
|
||||
|
||||
// @has user/type.F.html
|
||||
// @has - '//*[@class="rust item-decl"]//code' \
|
||||
// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();"
|
||||
pub use fn_type::F;
|
@ -29,7 +29,7 @@
|
||||
// @has impl_trait/fn.func5.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "func5("
|
||||
// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
|
||||
// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
|
||||
// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
|
||||
// @!has - '//pre[@class="rust item-decl"]' 'where'
|
||||
pub use impl_trait_aux::func5;
|
||||
|
||||
|
13
tests/rustdoc/inline_cross/non_lifetime_binders.rs
Normal file
13
tests/rustdoc/inline_cross/non_lifetime_binders.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// aux-crate:non_lifetime_binders=non_lifetime_binders.rs
|
||||
// edition: 2021
|
||||
#![crate_name = "user"]
|
||||
|
||||
// @has user/fn.f.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "f(_: impl for<T> Trait<T>)"
|
||||
pub use non_lifetime_binders::f;
|
||||
|
||||
// @has user/fn.g.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "g<T>(_: T)\
|
||||
// where \
|
||||
// T: for<U> Trait<U>"
|
||||
pub use non_lifetime_binders::g;
|
8
tests/ui/auto-traits/pre-cfg.rs
Normal file
8
tests/ui/auto-traits/pre-cfg.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// check-pass
|
||||
|
||||
#[cfg(FALSE)]
|
||||
auto trait Foo {}
|
||||
//~^ WARN `auto` traits are unstable
|
||||
//~| WARN unstable syntax can change at any point in the future, causing a hard error!
|
||||
|
||||
fn main() {}
|
13
tests/ui/auto-traits/pre-cfg.stderr
Normal file
13
tests/ui/auto-traits/pre-cfg.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
warning: `auto` traits are unstable
|
||||
--> $DIR/pre-cfg.rs:4:1
|
||||
|
|
||||
LL | auto trait Foo {}
|
||||
| ^^^^
|
||||
|
|
||||
= note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
|
||||
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -3,6 +3,7 @@
|
||||
// compile-flags: --test
|
||||
|
||||
#![feature(async_closure)]
|
||||
#![feature(auto_traits)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
|
@ -594,7 +594,7 @@ cc = ["@nnethercote"]
|
||||
[assign]
|
||||
warn_non_default_branch = true
|
||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||
users_on_vacation = ["jyn514", "jackh726"]
|
||||
users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin"]
|
||||
|
||||
[assign.adhoc_groups]
|
||||
compiler-team = [
|
||||
|
Loading…
Reference in New Issue
Block a user