diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 62dc7ae58a2f0..5d279943f1e83 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -603,6 +603,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "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); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad4edaba90b5..cc54cc5bebbdd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -813,7 +813,12 @@ impl<'a> Parser<'a> { 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()?; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index c27be8d2ffd31..c367b53b72027 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -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; /// } /// ``` /// /// 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; /// # } /// 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 { +/// // 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] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 6cf3bd619b255..e4ab1c17d9614 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -607,7 +607,7 @@ impl 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 @@ impl 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 diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 26aaa2414c979..ac7c800ff6f8c 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -380,7 +380,7 @@ impl RwLock { /// /// 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 @@ impl RwLock { /// /// 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); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index daf0798357b87..cf1f97c5b416c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -167,12 +167,14 @@ impl Step for Std { .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"); diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a06f31a932919..bdf6a0f6b239e 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -551,8 +551,8 @@ where 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 @@ where 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 diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index fcbcfbf5c67cf..eb18ecf662c14 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,9 +18,9 @@ use rustc_span::hygiene::MacroKind; 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 { 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) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5a1612e76e306..b9d7acee63c25 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( poly_trait_ref: ty::PolyTraitRef<'tcx>, bindings: ThinVec, ) -> 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::>(); - // 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)>, - >::default(); + // param index -> [(trait DefId, associated type name & generics, term)] + let mut impl_trait_proj = + FxHashMap::>)>>::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, +) -> Vec { + 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() +} diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 7b8f20326ed47..eea8c1906c5b5 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec { 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) -> ThinVec, bounds: &mut Vec, - mut bound_params: Vec, 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 { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1d8fa2e636edd..b891dc59cb1d0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1289,7 +1289,7 @@ impl Lifetime { pub(crate) enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: Box, rhs: Box, bound_params: Vec }, + EqPredicate { lhs: Type, rhs: Term }, } impl WherePredicate { @@ -1300,15 +1300,6 @@ impl WherePredicate { _ => 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)] diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 170e559e69803..1983bb11e5b11 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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 { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 0886501596056..472cde51be592 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -506,9 +506,8 @@ impl FromWithTcx for WherePredicate { 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) } } } } diff --git a/tests/rustdoc/inline_cross/auxiliary/fn-type.rs b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs new file mode 100644 index 0000000000000..dacda516bb88b --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs @@ -0,0 +1 @@ +pub type F = for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a (); diff --git a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 42cfc3dc3197d..fa61312ebc872 100644 --- a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -15,7 +15,7 @@ pub fn func4>(_x: T) {} pub fn func5( _f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>, - _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 { diff --git a/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs new file mode 100644 index 0000000000000..9170be16892b9 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs @@ -0,0 +1,10 @@ +#![feature(non_lifetime_binders)] + +pub trait Trait {} + +pub fn f(_: impl for Trait) {} + +pub fn g(_: T) +where + T: for Trait, +{} diff --git a/tests/rustdoc/inline_cross/fn-type.rs b/tests/rustdoc/inline_cross/fn-type.rs new file mode 100644 index 0000000000000..e65790d3b05aa --- /dev/null +++ b/tests/rustdoc/inline_cross/fn-type.rs @@ -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; diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs index 5c802c5148611..9b22026e49064 100644 --- a/tests/rustdoc/inline_cross/impl_trait.rs +++ b/tests/rustdoc/inline_cross/impl_trait.rs @@ -29,7 +29,7 @@ pub use impl_trait_aux::func4; // @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 = ()>," -// @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; diff --git a/tests/rustdoc/inline_cross/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/non_lifetime_binders.rs new file mode 100644 index 0000000000000..9d3085c3ef264 --- /dev/null +++ b/tests/rustdoc/inline_cross/non_lifetime_binders.rs @@ -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 Trait)" +pub use non_lifetime_binders::f; + +// @has user/fn.g.html +// @has - '//pre[@class="rust item-decl"]' "g(_: T)\ +// where \ +// T: for Trait" +pub use non_lifetime_binders::g; diff --git a/tests/ui/auto-traits/pre-cfg.rs b/tests/ui/auto-traits/pre-cfg.rs new file mode 100644 index 0000000000000..e6e840dcbab6f --- /dev/null +++ b/tests/ui/auto-traits/pre-cfg.rs @@ -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() {} diff --git a/tests/ui/auto-traits/pre-cfg.stderr b/tests/ui/auto-traits/pre-cfg.stderr new file mode 100644 index 0000000000000..6efa05b4326d5 --- /dev/null +++ b/tests/ui/auto-traits/pre-cfg.stderr @@ -0,0 +1,13 @@ +warning: `auto` traits are unstable + --> $DIR/pre-cfg.rs:4:1 + | +LL | auto trait Foo {} + | ^^^^ + | + = note: see issue #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 + +warning: 1 warning emitted + diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 816f99baa8495..8b4e6250a3080 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -3,6 +3,7 @@ // compile-flags: --test #![feature(async_closure)] +#![feature(auto_traits)] #![feature(box_patterns)] #![feature(const_trait_impl)] #![feature(decl_macro)] diff --git a/triagebot.toml b/triagebot.toml index aa1031133345a..4b051db0d73f2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -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 = [