Auto merge of #105070 - matthiaskrgr:rollup-9b25khj, r=matthiaskrgr

Rollup of 14 pull requests

Successful merges:

 - #103876 (type alias impl trait: add tests showing that hidden type only outlives lifetimes that occur in bounds)
 - #104427 (Explain why `rematch_impl` fails to be infallible)
 - #104436 (Add slice to the stack allocated string comment)
 - #104523 (Don't use periods in target names)
 - #104627 (Print all features with --print target-features)
 - #104911 (Make inferred_outlives_crate return Clause)
 - #105002 (Add `PathBuf::as_mut_os_string` and `Path::as_mut_os_str`)
 - #105023 (Statics used in reachable function's inline asm are reachable)
 - #105045 (`rustc_ast_{passes,pretty}`: remove `ref` patterns)
 - #105049 (Hermit: Minor build fixes)
 - #105051 (Replace a macro with a function)
 - #105062 (rustdoc: use shorthand background for rustdoc toggle CSS)
 - #105066 (move `candidate_from_obligation` out of assembly)
 - #105068 (Run patchelf also on rust-analyzer-proc-macro-srv.)

Failed merges:

 - #105050 (Remove useless borrows and derefs)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-11-30 00:42:43 +00:00
commit d38a99078c
38 changed files with 805 additions and 589 deletions

View file

@ -209,7 +209,7 @@ impl<'a> AstValidator<'a> {
// Mirrors `visit::walk_ty`, but tracks relevant state.
fn walk_ty(&mut self, t: &'a Ty) {
match t.kind {
match &t.kind {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
@ -217,7 +217,7 @@ impl<'a> AstValidator<'a> {
.with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
visit::walk_ty(this, t)
}),
TyKind::Path(ref qself, ref path) => {
TyKind::Path(qself, path) => {
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
@ -231,7 +231,7 @@ impl<'a> AstValidator<'a> {
// (for cases like `<impl Trait>::Foo>`)
// but we allow `impl Trait` in `GenericArgs`
// iff there are no more PathSegments.
if let Some(ref qself) = *qself {
if let Some(qself) = qself {
// `impl Trait` in `qself` is always illegal
self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
}
@ -738,8 +738,8 @@ impl<'a> AstValidator<'a> {
}
fn visit_ty_common(&mut self, ty: &'a Ty) {
match ty.kind {
TyKind::BareFn(ref bfty) => {
match &ty.kind {
TyKind::BareFn(bfty) => {
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
struct_span_err!(
@ -756,10 +756,10 @@ impl<'a> AstValidator<'a> {
self.maybe_lint_missing_abi(sig_span, ty.id);
}
}
TyKind::TraitObject(ref bounds, ..) => {
TyKind::TraitObject(bounds, ..) => {
let mut any_lifetime_bounds = false;
for bound in bounds {
if let GenericBound::Outlives(ref lifetime) = *bound {
if let GenericBound::Outlives(lifetime) = bound {
if any_lifetime_bounds {
struct_span_err!(
self.session,
@ -774,7 +774,7 @@ impl<'a> AstValidator<'a> {
}
}
}
TyKind::ImplTrait(_, ref bounds) => {
TyKind::ImplTrait(_, bounds) => {
if self.is_impl_trait_banned {
struct_span_err!(
self.session,
@ -842,8 +842,8 @@ fn validate_generic_param_order(
let (kind, bounds, span) = (&param.kind, &param.bounds, ident.span);
let (ord_kind, ident) = match &param.kind {
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()),
GenericParamKind::Type { default: _ } => (ParamKindOrd::TypeOrConst, ident.to_string()),
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
GenericParamKind::Type { .. } => (ParamKindOrd::TypeOrConst, ident.to_string()),
GenericParamKind::Const { ty, .. } => {
let ty = pprust::ty_to_string(ty);
(ParamKindOrd::TypeOrConst, format!("const {}: {}", ident, ty))
}
@ -948,8 +948,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
ExprKind::Paren(local_expr) => {
fn has_let_expr(expr: &Expr) -> bool {
match expr.kind {
ExprKind::Binary(_, ref lhs, ref rhs) => has_let_expr(lhs) || has_let_expr(rhs),
match &expr.kind {
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
ExprKind::Let(..) => true,
_ => false,
}
@ -1005,18 +1005,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_nomangle_item_asciionly(item.ident, item.span);
}
match item.kind {
match &item.kind {
ItemKind::Impl(box Impl {
unsafety,
polarity,
defaultness: _,
constness,
ref generics,
of_trait: Some(ref t),
ref self_ty,
ref items,
generics,
of_trait: Some(t),
self_ty,
items,
}) => {
self.with_in_trait_impl(true, Some(constness), |this| {
self.with_in_trait_impl(true, Some(*constness), |this| {
this.invalid_visibility(&item.vis, None);
if let TyKind::Err = self_ty.kind {
this.err_handler()
@ -1027,7 +1027,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.help("use `auto trait Trait {}` instead")
.emit();
}
if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
{
struct_span_err!(
this.session,
sp.to(t.path.span),
@ -1061,7 +1062,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
constness,
generics: _,
of_trait: None,
ref self_ty,
self_ty,
items: _,
}) => {
let error = |annotation_span, annotation| {
@ -1078,25 +1079,25 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
&item.vis,
Some(InvalidVisibilityNote::IndividualImplItems),
);
if let Unsafe::Yes(span) = unsafety {
if let &Unsafe::Yes(span) = unsafety {
error(span, "unsafe").code(error_code!(E0197)).emit();
}
if let ImplPolarity::Negative(span) = polarity {
if let &ImplPolarity::Negative(span) = polarity {
error(span, "negative").emit();
}
if let Defaultness::Default(def_span) = defaultness {
if let &Defaultness::Default(def_span) = defaultness {
error(def_span, "`default`")
.note("only trait implementations may be annotated with `default`")
.emit();
}
if let Const::Yes(span) = constness {
if let &Const::Yes(span) = constness {
error(span, "`const`")
.note("only trait implementations may be annotated with `const`")
.emit();
}
}
ItemKind::Fn(box Fn { defaultness, ref sig, ref generics, ref body }) => {
self.check_defaultness(item.span, defaultness);
ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
self.check_defaultness(item.span, *defaultness);
if body.is_none() {
self.session.emit_err(FnWithoutBody {
@ -1132,7 +1133,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
&item.vis,
Some(InvalidVisibilityNote::IndividualForeignItems),
);
if let Unsafe::Yes(span) = unsafety {
if let &Unsafe::Yes(span) = unsafety {
self.err_handler().span_err(span, "extern block cannot be declared unsafe");
}
if abi.is_none() {
@ -1142,7 +1143,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.extern_mod = old_item;
return; // Avoid visiting again.
}
ItemKind::Enum(ref def, _) => {
ItemKind::Enum(def, _) => {
for variant in &def.variants {
self.invalid_visibility(&variant.vis, None);
for field in variant.data.fields() {
@ -1150,8 +1151,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
ItemKind::Trait(box Trait { is_auto, ref generics, ref bounds, ref items, .. }) => {
if is_auto == IsAuto::Yes {
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
if *is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, item.ident.span);
self.deny_super_traits(bounds, item.ident.span);
@ -1171,8 +1172,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again
}
ItemKind::Mod(unsafety, ref mod_kind) => {
if let Unsafe::Yes(span) = unsafety {
ItemKind::Mod(unsafety, mod_kind) => {
if let &Unsafe::Yes(span) = unsafety {
self.err_handler().span_err(span, "module cannot be declared unsafe");
}
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
@ -1182,13 +1183,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_mod_file_item_asciionly(item.ident);
}
}
ItemKind::Union(ref vdata, ..) => {
ItemKind::Union(vdata, ..) => {
if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, "unions cannot have zero fields");
}
}
ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, def);
self.check_defaultness(item.span, *def);
self.session.emit_err(ConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
@ -1200,14 +1201,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
replace_span: self.ending_semi_or_hi(item.span),
});
}
ItemKind::TyAlias(box TyAlias {
defaultness,
where_clauses,
ref bounds,
ref ty,
..
}) => {
self.check_defaultness(item.span, defaultness);
ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
self.check_defaultness(item.span, *defaultness);
if ty.is_none() {
self.session.emit_err(TyAliasWithoutBody {
span: item.span,
@ -1266,8 +1261,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Mirrors `visit::walk_generic_args`, but tracks relevant state.
fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) {
match *generic_args {
GenericArgs::AngleBracketed(ref data) => {
match generic_args {
GenericArgs::AngleBracketed(data) => {
self.check_generic_args_before_constraints(data);
for arg in &data.args {
@ -1283,7 +1278,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
GenericArgs::Parenthesized(ref data) => {
GenericArgs::Parenthesized(data) => {
walk_list!(self, visit_ty, &data.inputs);
if let FnRetTy::Ty(ty) = &data.output {
// `-> Foo` syntax is essentially an associated type binding,
@ -1319,7 +1314,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
validate_generic_param_order(self.err_handler(), &generics.params, generics.span);
for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
if let WherePredicate::EqPredicate(predicate) = predicate {
deny_equality_constraints(self, predicate, generics);
}
}
@ -1368,7 +1363,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
if let GenericBound::Trait(ref poly, modify) = *bound {
if let GenericBound::Trait(poly, modify) = bound {
match (ctxt, modify) {
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
let mut err = self
@ -1573,8 +1568,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_item_named(item.ident, "const");
}
match item.kind {
AssocItemKind::Type(box TyAlias { ref generics, ref bounds, ref ty, .. })
match &item.kind {
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. })
if ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
@ -1586,7 +1581,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
walk_list!(self, visit_ty, ty);
}
AssocItemKind::Fn(box Fn { ref sig, ref generics, ref body, .. })
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
if self.in_const_trait_impl
|| ctxt == AssocCtxt::Trait
|| matches!(sig.header.constness, Const::Yes(_)) =>

View file

@ -198,8 +198,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_item(&mut self, i: &'a ast::Item) {
match i.kind {
ast::ItemKind::ForeignMod(ref foreign_module) => {
match &i.kind {
ast::ItemKind::ForeignMod(foreign_module) => {
if let Some(abi) = foreign_module.abi {
self.check_abi(abi, ast::Const::No);
}
@ -233,8 +233,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
if let &ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
&self,
negative_impls,
@ -267,7 +267,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_feature_post!(&self, decl_macro, i.span, msg);
}
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ref ty), .. }) => {
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
self.check_impl_trait(&ty)
}
@ -302,8 +302,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match ty.kind {
ast::TyKind::BareFn(ref bare_fn_ty) => {
match &ty.kind {
ast::TyKind::BareFn(bare_fn_ty) => {
// Function pointers cannot be `const`
self.check_extern(bare_fn_ty.ext, ast::Const::No);
}
@ -319,7 +319,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
if let ast::FnRetTy::Ty(ref output_ty) = *ret_ty {
if let ast::FnRetTy::Ty(output_ty) = ret_ty {
if let ast::TyKind::Never = output_ty.kind {
// Do nothing.
} else {
@ -455,9 +455,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match i.kind {
let is_fn = match &i.kind {
ast::AssocItemKind::Fn(_) => true,
ast::AssocItemKind::Type(box ast::TyAlias { ref ty, .. }) => {
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,

View file

@ -11,7 +11,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
use rustc_ast::util::parser;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, Mutability, PatKind};
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
use rustc_ast::{GenericArg, GenericBound, SelfKind, TraitBoundModifier};
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@ -64,6 +64,7 @@ impl<'a> Comments<'a> {
Comments { sm, comments, current: 0 }
}
// FIXME: This shouldn't probably clone lmao
pub fn next(&self) -> Option<Comment> {
self.comments.get(self.current).cloned()
}
@ -268,10 +269,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
let mut has_comment = false;
while let Some(ref cmnt) = self.next_comment() {
while let Some(cmnt) = self.next_comment() {
if cmnt.pos < pos {
has_comment = true;
self.print_comment(cmnt);
self.print_comment(&cmnt);
} else {
break;
}
@ -366,8 +367,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
if self.next_comment().is_none() {
self.hardbreak();
}
while let Some(ref cmnt) = self.next_comment() {
self.print_comment(cmnt)
while let Some(cmnt) = self.next_comment() {
self.print_comment(&cmnt)
}
}
@ -446,8 +447,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.hardbreak_if_not_bol();
}
self.maybe_print_comment(attr.span.lo());
match attr.kind {
ast::AttrKind::Normal(ref normal) => {
match &attr.kind {
ast::AttrKind::Normal(normal) => {
match attr.style {
ast::AttrStyle::Inner => self.word("#!["),
ast::AttrStyle::Outer => self.word("#["),
@ -456,7 +457,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.word("]");
}
ast::AttrKind::DocComment(comment_kind, data) => {
self.word(doc_comment_to_string(comment_kind, attr.style, data));
self.word(doc_comment_to_string(*comment_kind, attr.style, *data));
self.hardbreak()
}
}
@ -497,22 +498,22 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
match item {
ast::NestedMetaItem::MetaItem(ref mi) => self.print_meta_item(mi),
ast::NestedMetaItem::Lit(ref lit) => self.print_meta_item_lit(lit),
ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi),
ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit),
}
}
fn print_meta_item(&mut self, item: &ast::MetaItem) {
self.ibox(INDENT_UNIT);
match item.kind {
match &item.kind {
ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
ast::MetaItemKind::NameValue(ref value) => {
ast::MetaItemKind::NameValue(value) => {
self.print_path(&item.path, false, 0);
self.space();
self.word_space("=");
self.print_meta_item_lit(value);
}
ast::MetaItemKind::List(ref items) => {
ast::MetaItemKind::List(items) => {
self.print_path(&item.path, false, 0);
self.popen();
self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i));
@ -657,7 +658,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
fn print_path_segment(&mut self, segment: &ast::PathSegment, colons_before_params: bool) {
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
if let Some(ref args) = segment.args {
if let Some(args) = &segment.args {
self.print_generic_args(args, colons_before_params);
}
}
@ -712,19 +713,19 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
}
fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
match *nt {
token::NtExpr(ref e) => self.expr_to_string(e),
token::NtMeta(ref e) => self.attr_item_to_string(e),
token::NtTy(ref e) => self.ty_to_string(e),
token::NtPath(ref e) => self.path_to_string(e),
token::NtItem(ref e) => self.item_to_string(e),
token::NtBlock(ref e) => self.block_to_string(e),
token::NtStmt(ref e) => self.stmt_to_string(e),
token::NtPat(ref e) => self.pat_to_string(e),
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
match nt {
token::NtExpr(e) => self.expr_to_string(e),
token::NtMeta(e) => self.attr_item_to_string(e),
token::NtTy(e) => self.ty_to_string(e),
token::NtPath(e) => self.path_to_string(e),
token::NtItem(e) => self.item_to_string(e),
token::NtBlock(e) => self.block_to_string(e),
token::NtStmt(e) => self.stmt_to_string(e),
token::NtPat(e) => self.pat_to_string(e),
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(*e, *is_raw).to_string(),
token::NtLifetime(e) => e.to_string(),
token::NtLiteral(ref e) => self.expr_to_string(e),
token::NtVis(ref e) => self.vis_to_string(e),
token::NtLiteral(e) => self.expr_to_string(e),
token::NtVis(e) => self.vis_to_string(e),
}
}
@ -917,8 +918,8 @@ impl<'a> PrintState<'a> for State<'a> {
self.word("::")
}
match *args {
ast::GenericArgs::AngleBracketed(ref data) => {
match args {
ast::GenericArgs::AngleBracketed(data) => {
self.word("<");
self.commasep(Inconsistent, &data.args, |s, arg| match arg {
ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a),
@ -927,7 +928,7 @@ impl<'a> PrintState<'a> for State<'a> {
self.word(">")
}
ast::GenericArgs::Parenthesized(ref data) => {
ast::GenericArgs::Parenthesized(data) => {
self.word("(");
self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
self.word(")");
@ -1011,17 +1012,17 @@ impl<'a> State<'a> {
pub fn print_type(&mut self, ty: &ast::Ty) {
self.maybe_print_comment(ty.span.lo());
self.ibox(0);
match ty.kind {
ast::TyKind::Slice(ref ty) => {
match &ty.kind {
ast::TyKind::Slice(ty) => {
self.word("[");
self.print_type(ty);
self.word("]");
}
ast::TyKind::Ptr(ref mt) => {
ast::TyKind::Ptr(mt) => {
self.word("*");
self.print_mt(mt, true);
}
ast::TyKind::Rptr(ref lifetime, ref mt) => {
ast::TyKind::Rptr(lifetime, mt) => {
self.word("&");
self.print_opt_lifetime(lifetime);
self.print_mt(mt, false);
@ -1029,7 +1030,7 @@ impl<'a> State<'a> {
ast::TyKind::Never => {
self.word("!");
}
ast::TyKind::Tup(ref elts) => {
ast::TyKind::Tup(elts) => {
self.popen();
self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty));
if elts.len() == 1 {
@ -1037,36 +1038,36 @@ impl<'a> State<'a> {
}
self.pclose();
}
ast::TyKind::Paren(ref typ) => {
ast::TyKind::Paren(typ) => {
self.popen();
self.print_type(typ);
self.pclose();
}
ast::TyKind::BareFn(ref f) => {
ast::TyKind::BareFn(f) => {
self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params);
}
ast::TyKind::Path(None, ref path) => {
ast::TyKind::Path(None, path) => {
self.print_path(path, false, 0);
}
ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false),
ast::TyKind::TraitObject(ref bounds, syntax) => {
if syntax == ast::TraitObjectSyntax::Dyn {
ast::TyKind::Path(Some(qself), path) => self.print_qpath(path, qself, false),
ast::TyKind::TraitObject(bounds, syntax) => {
if *syntax == ast::TraitObjectSyntax::Dyn {
self.word_nbsp("dyn");
}
self.print_type_bounds(bounds);
}
ast::TyKind::ImplTrait(_, ref bounds) => {
ast::TyKind::ImplTrait(_, bounds) => {
self.word_nbsp("impl");
self.print_type_bounds(bounds);
}
ast::TyKind::Array(ref ty, ref length) => {
ast::TyKind::Array(ty, length) => {
self.word("[");
self.print_type(ty);
self.word("; ");
self.print_expr(&length.value);
self.word("]");
}
ast::TyKind::Typeof(ref e) => {
ast::TyKind::Typeof(e) => {
self.word("typeof(");
self.print_expr(&e.value);
self.word(")");
@ -1082,7 +1083,7 @@ impl<'a> State<'a> {
ast::TyKind::ImplicitSelf => {
self.word("Self");
}
ast::TyKind::MacCall(ref m) => {
ast::TyKind::MacCall(m) => {
self.print_mac(m);
}
ast::TyKind::CVarArgs => {
@ -1111,8 +1112,8 @@ impl<'a> State<'a> {
pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) {
self.maybe_print_comment(st.span.lo());
match st.kind {
ast::StmtKind::Local(ref loc) => {
match &st.kind {
ast::StmtKind::Local(loc) => {
self.print_outer_attributes(&loc.attrs);
self.space_if_not_bol();
self.ibox(INDENT_UNIT);
@ -1135,15 +1136,15 @@ impl<'a> State<'a> {
self.word(";");
self.end(); // `let` ibox
}
ast::StmtKind::Item(ref item) => self.print_item(item),
ast::StmtKind::Expr(ref expr) => {
ast::StmtKind::Item(item) => self.print_item(item),
ast::StmtKind::Expr(expr) => {
self.space_if_not_bol();
self.print_expr_outer_attr_style(expr, false);
if classify::expr_requires_semi_to_be_stmt(expr) {
self.word(";");
}
}
ast::StmtKind::Semi(ref expr) => {
ast::StmtKind::Semi(expr) => {
self.space_if_not_bol();
self.print_expr_outer_attr_style(expr, false);
self.word(";");
@ -1152,7 +1153,7 @@ impl<'a> State<'a> {
self.space_if_not_bol();
self.word(";");
}
ast::StmtKind::MacCall(ref mac) => {
ast::StmtKind::MacCall(mac) => {
self.space_if_not_bol();
self.print_outer_attributes(&mac.attrs);
self.print_mac(&mac.mac);
@ -1193,8 +1194,8 @@ impl<'a> State<'a> {
let has_attrs = self.print_inner_attributes(attrs);
for (i, st) in blk.stmts.iter().enumerate() {
match st.kind {
ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
match &st.kind {
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
self.maybe_print_comment(st.span.lo());
self.space_if_not_bol();
self.print_expr_outer_attr_style(expr, false);
@ -1362,7 +1363,7 @@ impl<'a> State<'a> {
pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) {
self.print_pat(&loc.pat);
if let Some(ref ty) = loc.ty {
if let Some(ty) = &loc.ty {
self.word_space(":");
self.print_type(ty);
}
@ -1386,7 +1387,7 @@ impl<'a> State<'a> {
for item_segment in &path.segments[qself.position..] {
self.word("::");
self.print_ident(item_segment.ident);
if let Some(ref args) = item_segment.args {
if let Some(args) = &item_segment.args {
self.print_generic_args(args, colons_before_params)
}
}
@ -1397,23 +1398,23 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::Pat(pat));
/* Pat isn't normalized, but the beauty of it
is that it doesn't matter */
match pat.kind {
match &pat.kind {
PatKind::Wild => self.word("_"),
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => {
if by_ref == ByRef::Yes {
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => {
if *by_ref == ByRef::Yes {
self.word_nbsp("ref");
}
if mutbl == Mutability::Mut {
if mutbl.is_mut() {
self.word_nbsp("mut");
}
self.print_ident(ident);
if let Some(ref p) = *sub {
self.print_ident(*ident);
if let Some(p) = sub {
self.space();
self.word_space("@");
self.print_pat(p);
}
}
PatKind::TupleStruct(ref qself, ref path, ref elts) => {
PatKind::TupleStruct(qself, path, elts) => {
if let Some(qself) = qself {
self.print_qpath(path, qself, true);
} else {
@ -1423,16 +1424,16 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
self.pclose();
}
PatKind::Or(ref pats) => {
PatKind::Or(pats) => {
self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p));
}
PatKind::Path(None, ref path) => {
PatKind::Path(None, path) => {
self.print_path(path, true, 0);
}
PatKind::Path(Some(ref qself), ref path) => {
PatKind::Path(Some(qself), path) => {
self.print_qpath(path, qself, false);
}
PatKind::Struct(ref qself, ref path, ref fields, etc) => {
PatKind::Struct(qself, path, fields, etc) => {
if let Some(qself) = qself {
self.print_qpath(path, qself, true);
} else {
@ -1458,7 +1459,7 @@ impl<'a> State<'a> {
},
|f| f.pat.span,
);
if etc {
if *etc {
if !fields.is_empty() {
self.word_space(",");
}
@ -1469,7 +1470,7 @@ impl<'a> State<'a> {
}
self.word("}");
}
PatKind::Tuple(ref elts) => {
PatKind::Tuple(elts) => {
self.popen();
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
if elts.len() == 1 {
@ -1477,13 +1478,13 @@ impl<'a> State<'a> {
}
self.pclose();
}
PatKind::Box(ref inner) => {
PatKind::Box(inner) => {
self.word("box ");
self.print_pat(inner);
}
PatKind::Ref(ref inner, mutbl) => {
PatKind::Ref(inner, mutbl) => {
self.word("&");
if mutbl == Mutability::Mut {
if mutbl.is_mut() {
self.word("mut ");
}
if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
@ -1494,12 +1495,12 @@ impl<'a> State<'a> {
self.print_pat(inner);
}
}
PatKind::Lit(ref e) => self.print_expr(&**e),
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
PatKind::Lit(e) => self.print_expr(&**e),
PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => {
if let Some(e) = begin {
self.print_expr(e);
}
match *end_kind {
match end_kind {
RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."),
RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="),
RangeEnd::Excluded => self.word(".."),
@ -1508,36 +1509,36 @@ impl<'a> State<'a> {
self.print_expr(e);
}
}
PatKind::Slice(ref elts) => {
PatKind::Slice(elts) => {
self.word("[");
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
self.word("]");
}
PatKind::Rest => self.word(".."),
PatKind::Paren(ref inner) => {
PatKind::Paren(inner) => {
self.popen();
self.print_pat(inner);
self.pclose();
}
PatKind::MacCall(ref m) => self.print_mac(m),
PatKind::MacCall(m) => self.print_mac(m),
}
self.ann.post(self, AnnNode::Pat(pat))
}
fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
match explicit_self.node {
match &explicit_self.node {
SelfKind::Value(m) => {
self.print_mutability(m, false);
self.print_mutability(*m, false);
self.word("self")
}
SelfKind::Region(ref lt, m) => {
SelfKind::Region(lt, m) => {
self.word("&");
self.print_opt_lifetime(lt);
self.print_mutability(m, false);
self.print_mutability(*m, false);
self.word("self")
}
SelfKind::Explicit(ref typ, m) => {
self.print_mutability(m, false);
SelfKind::Explicit(typ, m) => {
self.print_mutability(*m, false);
self.word("self");
self.word_space(":");
self.print_type(typ)
@ -1599,7 +1600,7 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, &generic_params, |s, param| {
s.print_outer_attributes_inline(&param.attrs);
match param.kind {
match &param.kind {
ast::GenericParamKind::Lifetime => {
let lt = ast::Lifetime { id: param.id, ident: param.ident };
s.print_lifetime(lt);
@ -1608,19 +1609,19 @@ impl<'a> State<'a> {
s.print_lifetime_bounds(&param.bounds)
}
}
ast::GenericParamKind::Type { ref default } => {
ast::GenericParamKind::Type { default } => {
s.print_ident(param.ident);
if !param.bounds.is_empty() {
s.word_nbsp(":");
s.print_type_bounds(&param.bounds);
}
if let Some(ref default) = default {
if let Some(default) = default {
s.space();
s.word_space("=");
s.print_type(default)
}
}
ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
ast::GenericParamKind::Const { ty, default, .. } => {
s.word_space("const");
s.print_ident(param.ident);
s.space();
@ -1630,7 +1631,7 @@ impl<'a> State<'a> {
s.word_nbsp(":");
s.print_type_bounds(&param.bounds);
}
if let Some(ref default) = default {
if let Some(default) = default {
s.space();
s.word_space("=");
s.print_expr(&default.value);

View file

@ -8,9 +8,9 @@ use rustc_ast::{self as ast, BlockCheckMode};
impl<'a> State<'a> {
fn print_else(&mut self, els: Option<&ast::Expr>) {
if let Some(_else) = els {
match _else.kind {
match &_else.kind {
// Another `else if` block.
ast::ExprKind::If(ref i, ref then, ref e) => {
ast::ExprKind::If(i, then, e) => {
self.cbox(INDENT_UNIT - 1);
self.ibox(0);
self.word(" else if ");
@ -20,7 +20,7 @@ impl<'a> State<'a> {
self.print_else(e.as_deref())
}
// Final `else` block.
ast::ExprKind::Block(ref b, _) => {
ast::ExprKind::Block(b, _) => {
self.cbox(INDENT_UNIT - 1);
self.ibox(0);
self.word(" else ");
@ -202,7 +202,7 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(segment.ident);
if let Some(ref args) = segment.args {
if let Some(args) = &segment.args {
self.print_generic_args(args, true);
}
self.print_call_post(base_args)
@ -284,73 +284,66 @@ impl<'a> State<'a> {
self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind {
ast::ExprKind::Box(ref expr) => {
match &expr.kind {
ast::ExprKind::Box(expr) => {
self.word_space("box");
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
}
ast::ExprKind::Array(ref exprs) => {
ast::ExprKind::Array(exprs) => {
self.print_expr_vec(exprs);
}
ast::ExprKind::ConstBlock(ref anon_const) => {
ast::ExprKind::ConstBlock(anon_const) => {
self.print_expr_anon_const(anon_const, attrs);
}
ast::ExprKind::Repeat(ref element, ref count) => {
ast::ExprKind::Repeat(element, count) => {
self.print_expr_repeat(element, count);
}
ast::ExprKind::Struct(ref se) => {
ast::ExprKind::Struct(se) => {
self.print_expr_struct(&se.qself, &se.path, &se.fields, &se.rest);
}
ast::ExprKind::Tup(ref exprs) => {
ast::ExprKind::Tup(exprs) => {
self.print_expr_tup(exprs);
}
ast::ExprKind::Call(ref func, ref args) => {
ast::ExprKind::Call(func, args) => {
self.print_expr_call(func, &args);
}
ast::ExprKind::MethodCall(box ast::MethodCall {
ref seg,
ref receiver,
ref args,
..
}) => {
ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
self.print_expr_method_call(seg, &receiver, &args);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, lhs, rhs);
ast::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(*op, lhs, rhs);
}
ast::ExprKind::Unary(op, ref expr) => {
self.print_expr_unary(op, expr);
ast::ExprKind::Unary(op, expr) => {
self.print_expr_unary(*op, expr);
}
ast::ExprKind::AddrOf(k, m, ref expr) => {
self.print_expr_addr_of(k, m, expr);
ast::ExprKind::AddrOf(k, m, expr) => {
self.print_expr_addr_of(*k, *m, expr);
}
ast::ExprKind::Lit(token_lit) => {
self.print_token_literal(token_lit, expr.span);
self.print_token_literal(*token_lit, expr.span);
}
ast::ExprKind::IncludedBytes(ref bytes) => {
ast::ExprKind::IncludedBytes(bytes) => {
let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
self.print_token_literal(lit, expr.span)
}
ast::ExprKind::Cast(ref expr, ref ty) => {
ast::ExprKind::Cast(expr, ty) => {
let prec = AssocOp::As.precedence() as i8;
self.print_expr_maybe_paren(expr, prec);
self.space();
self.word_space("as");
self.print_type(ty);
}
ast::ExprKind::Type(ref expr, ref ty) => {
ast::ExprKind::Type(expr, ty) => {
let prec = AssocOp::Colon.precedence() as i8;
self.print_expr_maybe_paren(expr, prec);
self.word_space(":");
self.print_type(ty);
}
ast::ExprKind::Let(ref pat, ref scrutinee, _) => {
ast::ExprKind::Let(pat, scrutinee, _) => {
self.print_let(pat, scrutinee);
}
ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
self.print_if(test, blk, elseopt.as_deref())
}
ast::ExprKind::While(ref test, ref blk, opt_label) => {
ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
ast::ExprKind::While(test, blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
@ -362,7 +355,7 @@ impl<'a> State<'a> {
self.space();
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => {
ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
@ -377,7 +370,7 @@ impl<'a> State<'a> {
self.space();
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Loop(ref blk, opt_label, _) => {
ast::ExprKind::Loop(blk, opt_label, _) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
@ -387,7 +380,7 @@ impl<'a> State<'a> {
self.word_nbsp("loop");
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Match(ref expr, ref arms) => {
ast::ExprKind::Match(expr, arms) => {
self.cbox(0);
self.ibox(0);
self.word_nbsp("match");
@ -402,18 +395,18 @@ impl<'a> State<'a> {
self.bclose(expr.span, empty);
}
ast::ExprKind::Closure(box ast::Closure {
ref binder,
binder,
capture_clause,
asyncness,
movability,
ref fn_decl,
ref body,
fn_decl,
body,
fn_decl_span: _,
}) => {
self.print_closure_binder(binder);
self.print_movability(movability);
self.print_asyncness(asyncness);
self.print_capture_clause(capture_clause);
self.print_movability(*movability);
self.print_asyncness(*asyncness);
self.print_capture_clause(*capture_clause);
self.print_fn_params_and_ret(fn_decl, true);
self.space();
@ -425,7 +418,7 @@ impl<'a> State<'a> {
// empty box to satisfy the close.
self.ibox(0);
}
ast::ExprKind::Block(ref blk, opt_label) => {
ast::ExprKind::Block(blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
@ -436,26 +429,26 @@ impl<'a> State<'a> {
self.ibox(0);
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Async(capture_clause, _, ref blk) => {
ast::ExprKind::Async(capture_clause, _, blk) => {
self.word_nbsp("async");
self.print_capture_clause(capture_clause);
self.print_capture_clause(*capture_clause);
// cbox/ibox in analogy to the `ExprKind::Block` arm above
self.cbox(0);
self.ibox(0);
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Await(ref expr) => {
ast::ExprKind::Await(expr) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.word(".await");
}
ast::ExprKind::Assign(ref lhs, ref rhs, _) => {
ast::ExprKind::Assign(lhs, rhs, _) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(lhs, prec + 1);
self.space();
self.word_space("=");
self.print_expr_maybe_paren(rhs, prec);
}
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
ast::ExprKind::AssignOp(op, lhs, rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(lhs, prec + 1);
self.space();
@ -463,45 +456,44 @@ impl<'a> State<'a> {
self.word_space("=");
self.print_expr_maybe_paren(rhs, prec);
}
ast::ExprKind::Field(ref expr, ident) => {
ast::ExprKind::Field(expr, ident) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(ident);
self.print_ident(*ident);
}
ast::ExprKind::Index(ref expr, ref index) => {
ast::ExprKind::Index(expr, index) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.word("[");
self.print_expr(index);
self.word("]");
}
ast::ExprKind::Range(ref start, ref end, limits) => {
ast::ExprKind::Range(start, end, limits) => {
// Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
// than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
// Here we use a fake precedence value so that any child with lower precedence than
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
let fake_prec = AssocOp::LOr.precedence() as i8;
if let Some(ref e) = *start {
if let Some(e) = start {
self.print_expr_maybe_paren(e, fake_prec);
}
if limits == ast::RangeLimits::HalfOpen {
self.word("..");
} else {
self.word("..=");
match limits {
ast::RangeLimits::HalfOpen => self.word(".."),
ast::RangeLimits::Closed => self.word("..="),
}
if let Some(ref e) = *end {
if let Some(e) = end {
self.print_expr_maybe_paren(e, fake_prec);
}
}
ast::ExprKind::Underscore => self.word("_"),
ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0),
ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true),
ast::ExprKind::Break(opt_label, ref opt_expr) => {
ast::ExprKind::Path(None, path) => self.print_path(path, true, 0),
ast::ExprKind::Path(Some(qself), path) => self.print_qpath(path, qself, true),
ast::ExprKind::Break(opt_label, opt_expr) => {
self.word("break");
if let Some(label) = opt_label {
self.space();
self.print_ident(label.ident);
}
if let Some(ref expr) = *opt_expr {
if let Some(expr) = opt_expr {
self.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
@ -513,45 +505,45 @@ impl<'a> State<'a> {
self.print_ident(label.ident);
}
}
ast::ExprKind::Ret(ref result) => {
ast::ExprKind::Ret(result) => {
self.word("return");
if let Some(ref expr) = *result {
if let Some(expr) = result {
self.word(" ");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::Yeet(ref result) => {
ast::ExprKind::Yeet(result) => {
self.word("do");
self.word(" ");
self.word("yeet");
if let Some(ref expr) = *result {
if let Some(expr) = result {
self.word(" ");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::InlineAsm(ref a) => {
ast::ExprKind::InlineAsm(a) => {
self.word("asm!");
self.print_inline_asm(a);
}
ast::ExprKind::MacCall(ref m) => self.print_mac(m),
ast::ExprKind::Paren(ref e) => {
ast::ExprKind::MacCall(m) => self.print_mac(m),
ast::ExprKind::Paren(e) => {
self.popen();
self.print_expr(e);
self.pclose();
}
ast::ExprKind::Yield(ref e) => {
ast::ExprKind::Yield(e) => {
self.word("yield");
if let Some(ref expr) = *e {
if let Some(expr) = e {
self.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::Try(ref e) => {
ast::ExprKind::Try(e) => {
self.print_expr_maybe_paren(e, parser::PREC_POSTFIX);
self.word("?")
}
ast::ExprKind::TryBlock(ref blk) => {
ast::ExprKind::TryBlock(blk) => {
self.cbox(0);
self.ibox(0);
self.word_nbsp("try");
@ -578,15 +570,15 @@ impl<'a> State<'a> {
self.print_outer_attributes(&arm.attrs);
self.print_pat(&arm.pat);
self.space();
if let Some(ref e) = arm.guard {
if let Some(e) = &arm.guard {
self.word_space("if");
self.print_expr(e);
self.space();
}
self.word_space("=>");
match arm.body.kind {
ast::ExprKind::Block(ref blk, opt_label) => {
match &arm.body.kind {
ast::ExprKind::Block(blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");

View file

@ -136,10 +136,10 @@ impl<'a> State<'a> {
self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs);
self.ann.pre(self, AnnNode::Item(item));
match item.kind {
match &item.kind {
ast::ItemKind::ExternCrate(orig_name) => {
self.head(visibility_qualified(&item.vis, "extern crate"));
if let Some(orig_name) = orig_name {
if let &Some(orig_name) = orig_name {
self.print_name(orig_name);
self.space();
self.word("as");
@ -150,35 +150,41 @@ impl<'a> State<'a> {
self.end(); // end inner head-block
self.end(); // end outer head-block
}
ast::ItemKind::Use(ref tree) => {
ast::ItemKind::Use(tree) => {
self.print_visibility(&item.vis);
self.word_nbsp("use");
self.print_use_tree(tree);
self.word(";");
}
ast::ItemKind::Static(ref ty, mutbl, ref body) => {
ast::ItemKind::Static(ty, mutbl, body) => {
let def = ast::Defaultness::Final;
self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def);
self.print_item_const(
item.ident,
Some(*mutbl),
ty,
body.as_deref(),
&item.vis,
def,
);
}
ast::ItemKind::Const(def, ref ty, ref body) => {
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
ast::ItemKind::Const(def, ty, body) => {
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, *def);
}
ast::ItemKind::Fn(box ast::Fn { defaultness, ref sig, ref generics, ref body }) => {
let body = body.as_deref();
ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(
sig,
item.ident,
generics,
&item.vis,
defaultness,
body,
*defaultness,
body.as_deref(),
&item.attrs,
);
}
ast::ItemKind::Mod(unsafety, ref mod_kind) => {
ast::ItemKind::Mod(unsafety, mod_kind) => {
self.head(Self::to_string(|s| {
s.print_visibility(&item.vis);
s.print_unsafety(unsafety);
s.print_unsafety(*unsafety);
s.word("mod");
}));
self.print_ident(item.ident);
@ -201,7 +207,7 @@ impl<'a> State<'a> {
}
}
}
ast::ItemKind::ForeignMod(ref nmod) => {
ast::ItemKind::ForeignMod(nmod) => {
self.head(Self::to_string(|s| {
s.print_unsafety(nmod.unsafety);
s.word("extern");
@ -215,7 +221,7 @@ impl<'a> State<'a> {
let empty = item.attrs.is_empty() && nmod.items.is_empty();
self.bclose(item.span, empty);
}
ast::ItemKind::GlobalAsm(ref asm) => {
ast::ItemKind::GlobalAsm(asm) => {
self.head(visibility_qualified(&item.vis, "global_asm!"));
self.print_inline_asm(asm);
self.word(";");
@ -224,32 +230,31 @@ impl<'a> State<'a> {
}
ast::ItemKind::TyAlias(box ast::TyAlias {
defaultness,
ref generics,
generics,
where_clauses,
where_predicates_split,
ref bounds,
ref ty,
bounds,
ty,
}) => {
let ty = ty.as_deref();
self.print_associated_type(
item.ident,
generics,
where_clauses,
where_predicates_split,
*where_clauses,
*where_predicates_split,
bounds,
ty,
ty.as_deref(),
&item.vis,
defaultness,
*defaultness,
);
}
ast::ItemKind::Enum(ref enum_definition, ref params) => {
ast::ItemKind::Enum(enum_definition, params) => {
self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
}
ast::ItemKind::Struct(ref struct_def, ref generics) => {
ast::ItemKind::Struct(struct_def, generics) => {
self.head(visibility_qualified(&item.vis, "struct"));
self.print_struct(struct_def, generics, item.ident, item.span, true);
}
ast::ItemKind::Union(ref struct_def, ref generics) => {
ast::ItemKind::Union(struct_def, generics) => {
self.head(visibility_qualified(&item.vis, "union"));
self.print_struct(struct_def, generics, item.ident, item.span, true);
}
@ -258,15 +263,15 @@ impl<'a> State<'a> {
polarity,
defaultness,
constness,
ref generics,
ref of_trait,
ref self_ty,
ref items,
generics,
of_trait,
self_ty,
items,
}) => {
self.head("");
self.print_visibility(&item.vis);
self.print_defaultness(defaultness);
self.print_unsafety(unsafety);
self.print_defaultness(*defaultness);
self.print_unsafety(*unsafety);
self.word("impl");
if generics.params.is_empty() {
@ -276,13 +281,13 @@ impl<'a> State<'a> {
self.space();
}
self.print_constness(constness);
self.print_constness(*constness);
if let ast::ImplPolarity::Negative(_) = polarity {
self.word("!");
}
if let Some(ref t) = *of_trait {
if let Some(t) = of_trait {
self.print_trait_ref(t);
self.space();
self.word_space("for");
@ -303,21 +308,21 @@ impl<'a> State<'a> {
ast::ItemKind::Trait(box ast::Trait {
is_auto,
unsafety,
ref generics,
ref bounds,
ref items,
generics,
bounds,
items,
..
}) => {
self.head("");
self.print_visibility(&item.vis);
self.print_unsafety(unsafety);
self.print_is_auto(is_auto);
self.print_unsafety(*unsafety);
self.print_is_auto(*is_auto);
self.word_nbsp("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
@ -339,14 +344,14 @@ impl<'a> State<'a> {
let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty);
}
ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
ast::ItemKind::TraitAlias(generics, bounds) => {
self.head(visibility_qualified(&item.vis, "trait"));
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
@ -364,13 +369,13 @@ impl<'a> State<'a> {
self.end(); // end inner head-block
self.end(); // end outer head-block
}
ast::ItemKind::MacCall(ref mac) => {
ast::ItemKind::MacCall(mac) => {
self.print_mac(mac);
if mac.args.need_semicolon() {
self.word(";");
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
ast::ItemKind::MacroDef(macro_def) => {
self.print_mac_def(macro_def, &item.ident, item.span, |state| {
state.print_visibility(&item.vis)
});
@ -412,11 +417,11 @@ impl<'a> State<'a> {
}
pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) {
match vis.kind {
match &vis.kind {
ast::VisibilityKind::Public => self.word_nbsp("pub"),
ast::VisibilityKind::Restricted { ref path, id: _, shorthand } => {
ast::VisibilityKind::Restricted { path, shorthand, .. } => {
let path = Self::to_string(|s| s.print_path(path, false, 0));
if shorthand && (path == "crate" || path == "self" || path == "super") {
if *shorthand && (path == "crate" || path == "self" || path == "super") {
self.word_nbsp(format!("pub({})", path))
} else {
self.word_nbsp(format!("pub(in {})", path))
@ -465,7 +470,7 @@ impl<'a> State<'a> {
) {
self.print_ident(ident);
self.print_generic_params(&generics.params);
match struct_def {
match &struct_def {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
if let ast::VariantData::Tuple(..) = struct_def {
self.popen();
@ -484,7 +489,7 @@ impl<'a> State<'a> {
self.end();
self.end(); // Close the outer-box.
}
ast::VariantData::Struct(ref fields, ..) => {
ast::VariantData::Struct(fields, ..) => {
self.print_where_clause(&generics.where_clause);
self.print_record_struct_body(fields, span);
}
@ -496,7 +501,7 @@ impl<'a> State<'a> {
self.print_visibility(&v.vis);
let generics = ast::Generics::default();
self.print_struct(&v.data, &generics, v.ident, v.span, false);
if let Some(ref d) = v.disr_expr {
if let Some(d) = &v.disr_expr {
self.space();
self.word_space("=");
self.print_expr(&d.value)
@ -657,10 +662,10 @@ impl<'a> State<'a> {
}
fn print_use_tree(&mut self, tree: &ast::UseTree) {
match tree.kind {
match &tree.kind {
ast::UseTreeKind::Simple(rename, ..) => {
self.print_path(&tree.prefix, false, 0);
if let Some(rename) = rename {
if let &Some(rename) = rename {
self.nbsp();
self.word_nbsp("as");
self.print_ident(rename);
@ -673,7 +678,7 @@ impl<'a> State<'a> {
}
self.word("*");
}
ast::UseTreeKind::Nested(ref items) => {
ast::UseTreeKind::Nested(items) => {
if !tree.prefix.segments.is_empty() {
self.print_path(&tree.prefix, false, 0);
self.word("::");

View file

@ -1705,6 +1705,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
});
}
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]
fn check_member_constraints(
&self,
infcx: &InferCtxt<'tcx>,
@ -1712,22 +1713,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) {
let member_constraints = self.member_constraints.clone();
for m_c_i in member_constraints.all_indices() {
debug!("check_member_constraint(m_c_i={:?})", m_c_i);
debug!(?m_c_i);
let m_c = &member_constraints[m_c_i];
let member_region_vid = m_c.member_region_vid;
debug!(
"check_member_constraint: member_region_vid={:?} with value {}",
member_region_vid,
self.region_value_str(member_region_vid),
?member_region_vid,
value = ?self.region_value_str(member_region_vid),
);
let choice_regions = member_constraints.choice_regions(m_c_i);
debug!("check_member_constraint: choice_regions={:?}", choice_regions);
debug!(?choice_regions);
// Did the member region wind up equal to any of the option regions?
if let Some(o) =
choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
{
debug!("check_member_constraint: evaluated as equal to {:?}", o);
debug!("evaluated as equal to {:?}", o);
continue;
}

View file

@ -292,30 +292,33 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> {
}
fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
let mut target_features = llvm_target_features(tm);
let mut llvm_target_features = llvm_target_features(tm);
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
let mut rustc_target_features = supported_target_features(sess)
.iter()
.filter_map(|(feature, _gate)| {
for llvm_feature in to_llvm_features(sess, *feature) {
.map(|(feature, _gate)| {
let desc = if let Some(llvm_feature) = to_llvm_features(sess, *feature).first() {
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok().map(
|index| {
let (_f, desc) = target_features.remove(index);
(*feature, desc)
},
) {
Some(v) => return Some(v),
None => {}
match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() {
Some(index) => {
known_llvm_target_features.insert(llvm_feature);
llvm_target_features[index].1
}
None => "",
}
}
None
} else {
""
};
(*feature, desc)
})
.collect::<Vec<_>>();
rustc_target_features.extend_from_slice(&[(
"crt-static",
"Enables C Run-time Libraries to be statically linked",
)]);
let max_feature_len = target_features
llvm_target_features.retain(|(f, _d)| !known_llvm_target_features.contains(f));
let max_feature_len = llvm_target_features
.iter()
.chain(rustc_target_features.iter())
.map(|(feature, _desc)| feature.len())
@ -327,10 +330,10 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
println!(" {1:0$} - {2}.", max_feature_len, feature, desc);
}
println!("\nCode-generation features supported by LLVM for this target:");
for (feature, desc) in &target_features {
for (feature, desc) in &llvm_target_features {
println!(" {1:0$} - {2}.", max_feature_len, feature, desc);
}
if target_features.is_empty() {
if llvm_target_features.is_empty() {
println!(" Target features listing is not supported by this LLVM version.");
}
println!("\nUse +feature to enable a feature, or -feature to disable it.");

View file

@ -33,7 +33,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@ -1366,12 +1366,14 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
"predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
def_id, inferred_outlives,
);
let inferred_outlives_iter =
inferred_outlives.iter().map(|(clause, span)| ((*clause).to_predicate(tcx), *span));
if result.predicates.is_empty() {
result.predicates = inferred_outlives;
result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
} else {
result.predicates = tcx
.arena
.alloc_from_iter(result.predicates.iter().chain(inferred_outlives).copied());
result.predicates = tcx.arena.alloc_from_iter(
result.predicates.into_iter().copied().chain(inferred_outlives_iter),
);
}
}

View file

@ -3,7 +3,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
@ -17,7 +17,7 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
}
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Clause<'_>, Span)] {
let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization()
@ -50,12 +50,10 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec<String> = predicates
.iter()
.map(|(out_pred, _)| match out_pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(p)) => {
p.to_string()
}
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(p)) => p.to_string(),
err => bug!("unexpected predicate {:?}", err),
.map(|(out_pred, _)| match out_pred {
ty::Clause::RegionOutlives(p) => p.to_string(),
ty::Clause::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected clause {:?}", err),
})
.collect();
pred.sort();
@ -103,19 +101,11 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((
ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
ty::OutlivesPredicate(ty1, *region2),
)))
.to_predicate(tcx),
ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
span,
)),
GenericArgKind::Lifetime(region1) => Some((
ty::Binder::dummy(ty::PredicateKind::Clause(
ty::Clause::RegionOutlives(ty::OutlivesPredicate(
region1, *region2,
)),
))
.to_predicate(tcx),
ty::Clause::RegionOutlives(ty::OutlivesPredicate(region1, *region2)),
span,
)),
GenericArgKind::Const(_) => {

View file

@ -2046,16 +2046,13 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
impl ExplicitOutlivesRequirements {
fn lifetimes_outliving_lifetime<'tcx>(
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
def_id: DefId,
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
a,
b,
))) => match *a {
.filter_map(|(clause, _)| match *clause {
ty::Clause::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
_ => None,
},
@ -2065,16 +2062,15 @@ impl ExplicitOutlivesRequirements {
}
fn lifetimes_outliving_type<'tcx>(
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
index: u32,
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
a,
b,
))) => a.is_param(index).then_some(b),
.filter_map(|(clause, _)| match *clause {
ty::Clause::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
a.is_param(index).then_some(b)
}
_ => None,
})
.collect()

View file

@ -353,7 +353,7 @@ define_tables! {
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
// As an optimization, a missing entry indicates an empty `&[]`.
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
type_of: Table<DefIndex, LazyValue<Ty<'static>>>,
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,

View file

@ -562,7 +562,7 @@ rustc_queries! {
/// Returns the inferred outlives predicates (e.g., for `struct
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] {
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern

View file

@ -345,6 +345,14 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
fn decode(decoder: &mut D) -> &'tcx Self {
decoder.interner().arena.alloc_from_iter(
(0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
)
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
for ty::List<ty::BoundVariableKind>
{

View file

@ -734,7 +734,7 @@ pub struct CratePredicatesMap<'tcx> {
/// For each struct with outlive bounds, maps to a vector of the
/// predicate of its outlive bounds. If an item has no outlives
/// bounds, it will have no entry.
pub predicates: FxHashMap<DefId, &'tcx [(Predicate<'tcx>, Span)]>,
pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
}
impl<'tcx> Predicate<'tcx> {
@ -1167,6 +1167,13 @@ impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tc
}
}
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Clause<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {

View file

@ -5,7 +5,7 @@ use rustc_index::vec::{Idx, IndexVec};
use crate::middle::exported_symbols::ExportedSymbol;
use crate::mir::Body;
use crate::ty::{
self, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
};
pub trait ParameterizedOverTcx: 'static {
@ -121,6 +121,7 @@ parameterized_over_tcx! {
TraitRef,
Const,
Predicate,
Clause,
GeneratorDiagnosticData,
Body,
ExportedSymbol,

View file

@ -116,6 +116,17 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
intravisit::walk_expr(self, expr)
}
fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
for (op, _) in asm.operands {
if let hir::InlineAsmOperand::SymStatic { def_id, .. } = op {
if let Some(def_id) = def_id.as_local() {
self.reachable_symbols.insert(def_id);
}
}
}
intravisit::walk_inline_asm(self, asm, id);
}
}
impl<'tcx> ReachableContext<'tcx> {

View file

@ -818,6 +818,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)

View file

@ -1,22 +1,19 @@
#![macro_use]
macro_rules! max_leb128_len {
($int_ty:ty) => {
// The longest LEB128 encoding for an integer uses 7 bits per byte.
(std::mem::size_of::<$int_ty>() * 8 + 6) / 7
};
/// Returns the length of the longest LEB128 encoding for `T`, assuming `T` is an integer type
pub const fn max_leb128_len<T>() -> usize {
// The longest LEB128 encoding for an integer uses 7 bits per byte.
(std::mem::size_of::<T>() * 8 + 6) / 7
}
/// Returns the longest LEB128 encoding of all supported integer types.
pub const fn max_leb128_len() -> usize {
max_leb128_len!(u128)
/// Returns the length of the longest LEB128 encoding of all supported integer types.
pub const fn largest_max_leb128_len() -> usize {
max_leb128_len::<u128>()
}
macro_rules! impl_write_unsigned_leb128 {
($fn_name:ident, $int_ty:ty) => {
#[inline]
pub fn $fn_name(
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len!($int_ty)],
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
mut value: $int_ty,
) -> &[u8] {
let mut i = 0;
@ -90,7 +87,7 @@ macro_rules! impl_write_signed_leb128 {
($fn_name:ident, $int_ty:ty) => {
#[inline]
pub fn $fn_name(
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len!($int_ty)],
out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
mut value: $int_ty,
) -> &[u8] {
let mut i = 0;

View file

@ -1,4 +1,4 @@
use crate::leb128::{self, max_leb128_len};
use crate::leb128::{self, largest_max_leb128_len};
use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
use std::convert::TryInto;
use std::fs::File;
@ -32,7 +32,7 @@ impl MemEncoder {
macro_rules! write_leb128 {
($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
const MAX_ENCODED_LEN: usize = max_leb128_len!($int_ty);
const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
let old_len = $enc.data.len();
if MAX_ENCODED_LEN > $enc.data.capacity() - old_len {
@ -186,12 +186,12 @@ impl FileEncoder {
pub fn with_capacity<P: AsRef<Path>>(path: P, capacity: usize) -> io::Result<Self> {
// Require capacity at least as large as the largest LEB128 encoding
// here, so that we don't have to check or handle this on every write.
assert!(capacity >= max_leb128_len());
assert!(capacity >= largest_max_leb128_len());
// Require capacity small enough such that some capacity checks can be
// done using guaranteed non-overflowing add rather than sub, which
// shaves an instruction off those code paths (on x86 at least).
assert!(capacity <= usize::MAX - max_leb128_len());
assert!(capacity <= usize::MAX - largest_max_leb128_len());
// Create the file for reading and writing, because some encoders do both
// (e.g. the metadata encoder when -Zmeta-stats is enabled)
@ -411,7 +411,7 @@ impl Drop for FileEncoder {
macro_rules! file_encoder_write_leb128 {
($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
const MAX_ENCODED_LEN: usize = max_leb128_len!($int_ty);
const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
// We ensure this during `FileEncoder` construction.
debug_assert!($enc.capacity() >= MAX_ENCODED_LEN);

View file

@ -1250,8 +1250,8 @@ supported_targets! {
("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
("aarch64-unknown-nto-qnx7.1.0", aarch64_unknown_nto_qnx_710),
("x86_64-pc-nto-qnx7.1.0", x86_64_pc_nto_qnx710),
("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx_710),
("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710),
}
/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>

View file

@ -9,225 +9,18 @@ use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_target::spec::abi::Abi;
use crate::traits;
use crate::traits::coherence::Conflict;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{util, SelectionResult};
use crate::traits::{ErrorReporting, Overflow, Unimplemented};
use crate::traits::util;
use super::BuiltinImplConditions;
use super::IntercrateAmbiguityCause;
use super::OverflowError;
use super::SelectionCandidate::{self, *};
use super::{EvaluatedCandidate, SelectionCandidateSet, SelectionContext, TraitObligationStack};
use super::SelectionCandidate::*;
use super::{SelectionCandidateSet, SelectionContext, TraitObligationStack};
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn candidate_from_obligation<'o>(
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
// Watch out for overflow. This intentionally bypasses (and does
// not update) the cache.
self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
// Check the cache. Note that we freshen the trait-ref
// separately rather than using `stack.fresh_trait_ref` --
// this is because we want the unbound variables to be
// replaced with fresh types starting from index 0.
let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate);
debug!(?cache_fresh_trait_pred);
debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
if let Some(c) =
self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred)
{
debug!("CACHE HIT");
return c;
}
// If no match, compute result and insert into cache.
//
// FIXME(nikomatsakis) -- this cache is not taking into
// account cycles that may have occurred in forming the
// candidate. I don't know of any specific problems that
// result but it seems awfully suspicious.
let (candidate, dep_node) =
self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
debug!("CACHE MISS");
self.insert_candidate_cache(
stack.obligation.param_env,
cache_fresh_trait_pred,
dep_node,
candidate.clone(),
);
candidate
}
fn candidate_from_obligation_no_cache<'o>(
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
if let Err(conflict) = self.is_knowable(stack) {
debug!("coherence stage: not knowable");
if self.intercrate_ambiguity_causes.is_some() {
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
// Heuristics: show the diagnostics when there are no candidates in crate.
if let Ok(candidate_set) = self.assemble_candidates(stack) {
let mut no_candidates_apply = true;
for c in candidate_set.vec.iter() {
if self.evaluate_candidate(stack, &c)?.may_apply() {
no_candidates_apply = false;
break;
}
}
if !candidate_set.ambiguous && no_candidates_apply {
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
let self_ty = trait_ref.self_ty();
let (trait_desc, self_desc) = with_no_trimmed_paths!({
let trait_desc = trait_ref.print_only_trait_path().to_string();
let self_desc = if self_ty.has_concrete_skeleton() {
Some(self_ty.to_string())
} else {
None
};
(trait_desc, self_desc)
});
let cause = if let Conflict::Upstream = conflict {
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
} else {
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
};
debug!(?cause, "evaluate_stack: pushing cause");
self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
}
}
}
return Ok(None);
}
let candidate_set = self.assemble_candidates(stack)?;
if candidate_set.ambiguous {
debug!("candidate set contains ambig");
return Ok(None);
}
let candidates = candidate_set.vec;
debug!(?stack, ?candidates, "assembled {} candidates", candidates.len());
// At this point, we know that each of the entries in the
// candidate set is *individually* applicable. Now we have to
// figure out if they contain mutual incompatibilities. This
// frequently arises if we have an unconstrained input type --
// for example, we are looking for `$0: Eq` where `$0` is some
// unconstrained type variable. In that case, we'll get a
// candidate which assumes $0 == int, one that assumes `$0 ==
// usize`, etc. This spells an ambiguity.
let mut candidates = self.filter_impls(candidates, stack.obligation);
// If there is more than one candidate, first winnow them down
// by considering extra conditions (nested obligations and so
// forth). We don't winnow if there is exactly one
// candidate. This is a relatively minor distinction but it
// can lead to better inference and error-reporting. An
// example would be if there was an impl:
//
// impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
//
// and we were to see some code `foo.push_clone()` where `boo`
// is a `Vec<Bar>` and `Bar` does not implement `Clone`. If
// we were to winnow, we'd wind up with zero candidates.
// Instead, we select the right impl now but report "`Bar` does
// not implement `Clone`".
if candidates.len() == 1 {
return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation);
}
// Winnow, but record the exact outcome of evaluation, which
// is needed for specialization. Propagate overflow if it occurs.
let mut candidates = candidates
.into_iter()
.map(|c| match self.evaluate_candidate(stack, &c) {
Ok(eval) if eval.may_apply() => {
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
}
Ok(_) => Ok(None),
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
})
.flat_map(Result::transpose)
.collect::<Result<Vec<_>, _>>()?;
debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
let needs_infer = stack.obligation.predicate.has_non_region_infer();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
// resolving specializations.
if candidates.len() > 1 {
let mut i = 0;
while i < candidates.len() {
let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
self.candidate_should_be_dropped_in_favor_of(
&candidates[i],
&candidates[j],
needs_infer,
)
});
if is_dup {
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
candidates.swap_remove(i);
} else {
debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
i += 1;
// If there are *STILL* multiple candidates, give up
// and report ambiguity.
if i > 1 {
debug!("multiple matches, ambig");
return Ok(None);
}
}
}
}
// If there are *NO* candidates, then there are no impls --
// that we know of, anyway. Note that in the case where there
// are unbound type variables within the obligation, it might
// be the case that you could still satisfy the obligation
// from another crate by instantiating the type variables with
// a type from another crate that does have an impl. This case
// is checked for in `evaluate_stack` (and hence users
// who might care about this case, like coherence, should use
// that function).
if candidates.is_empty() {
// If there's an error type, 'downgrade' our result from
// `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
// emitting additional spurious errors, since we're guaranteed
// to have emitted at least one.
if stack.obligation.predicate.references_error() {
debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous");
return Ok(None);
}
return Err(Unimplemented);
}
// Just one candidate left.
self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation)
}
#[instrument(skip(self, stack), level = "debug")]
pub(super) fn assemble_candidates<'o>(
&mut self,

View file

@ -30,6 +30,7 @@ use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
use crate::traits::Unimplemented;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
@ -55,6 +56,7 @@ use std::fmt::{self, Display};
use std::iter;
pub use rustc_middle::traits::select::*;
use rustc_middle::ty::print::with_no_trimmed_paths;
mod candidate_assembly;
mod confirmation;
@ -305,6 +307,208 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.candidate_from_obligation(&stack)
}
#[instrument(level = "debug", skip(self), ret)]
fn candidate_from_obligation<'o>(
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
// Watch out for overflow. This intentionally bypasses (and does
// not update) the cache.
self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
// Check the cache. Note that we freshen the trait-ref
// separately rather than using `stack.fresh_trait_ref` --
// this is because we want the unbound variables to be
// replaced with fresh types starting from index 0.
let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate);
debug!(?cache_fresh_trait_pred);
debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
if let Some(c) =
self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred)
{
debug!("CACHE HIT");
return c;
}
// If no match, compute result and insert into cache.
//
// FIXME(nikomatsakis) -- this cache is not taking into
// account cycles that may have occurred in forming the
// candidate. I don't know of any specific problems that
// result but it seems awfully suspicious.
let (candidate, dep_node) =
self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
debug!("CACHE MISS");
self.insert_candidate_cache(
stack.obligation.param_env,
cache_fresh_trait_pred,
dep_node,
candidate.clone(),
);
candidate
}
fn candidate_from_obligation_no_cache<'o>(
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
if let Err(conflict) = self.is_knowable(stack) {
debug!("coherence stage: not knowable");
if self.intercrate_ambiguity_causes.is_some() {
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
// Heuristics: show the diagnostics when there are no candidates in crate.
if let Ok(candidate_set) = self.assemble_candidates(stack) {
let mut no_candidates_apply = true;
for c in candidate_set.vec.iter() {
if self.evaluate_candidate(stack, &c)?.may_apply() {
no_candidates_apply = false;
break;
}
}
if !candidate_set.ambiguous && no_candidates_apply {
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
let self_ty = trait_ref.self_ty();
let (trait_desc, self_desc) = with_no_trimmed_paths!({
let trait_desc = trait_ref.print_only_trait_path().to_string();
let self_desc = if self_ty.has_concrete_skeleton() {
Some(self_ty.to_string())
} else {
None
};
(trait_desc, self_desc)
});
let cause = if let Conflict::Upstream = conflict {
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
} else {
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
};
debug!(?cause, "evaluate_stack: pushing cause");
self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
}
}
}
return Ok(None);
}
let candidate_set = self.assemble_candidates(stack)?;
if candidate_set.ambiguous {
debug!("candidate set contains ambig");
return Ok(None);
}
let candidates = candidate_set.vec;
debug!(?stack, ?candidates, "assembled {} candidates", candidates.len());
// At this point, we know that each of the entries in the
// candidate set is *individually* applicable. Now we have to
// figure out if they contain mutual incompatibilities. This
// frequently arises if we have an unconstrained input type --
// for example, we are looking for `$0: Eq` where `$0` is some
// unconstrained type variable. In that case, we'll get a
// candidate which assumes $0 == int, one that assumes `$0 ==
// usize`, etc. This spells an ambiguity.
let mut candidates = self.filter_impls(candidates, stack.obligation);
// If there is more than one candidate, first winnow them down
// by considering extra conditions (nested obligations and so
// forth). We don't winnow if there is exactly one
// candidate. This is a relatively minor distinction but it
// can lead to better inference and error-reporting. An
// example would be if there was an impl:
//
// impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
//
// and we were to see some code `foo.push_clone()` where `boo`
// is a `Vec<Bar>` and `Bar` does not implement `Clone`. If
// we were to winnow, we'd wind up with zero candidates.
// Instead, we select the right impl now but report "`Bar` does
// not implement `Clone`".
if candidates.len() == 1 {
return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation);
}
// Winnow, but record the exact outcome of evaluation, which
// is needed for specialization. Propagate overflow if it occurs.
let mut candidates = candidates
.into_iter()
.map(|c| match self.evaluate_candidate(stack, &c) {
Ok(eval) if eval.may_apply() => {
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
}
Ok(_) => Ok(None),
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
})
.flat_map(Result::transpose)
.collect::<Result<Vec<_>, _>>()?;
debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
let needs_infer = stack.obligation.predicate.has_non_region_infer();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
// resolving specializations.
if candidates.len() > 1 {
let mut i = 0;
while i < candidates.len() {
let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
self.candidate_should_be_dropped_in_favor_of(
&candidates[i],
&candidates[j],
needs_infer,
)
});
if is_dup {
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
candidates.swap_remove(i);
} else {
debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
i += 1;
// If there are *STILL* multiple candidates, give up
// and report ambiguity.
if i > 1 {
debug!("multiple matches, ambig");
return Ok(None);
}
}
}
}
// If there are *NO* candidates, then there are no impls --
// that we know of, anyway. Note that in the case where there
// are unbound type variables within the obligation, it might
// be the case that you could still satisfy the obligation
// from another crate by instantiating the type variables with
// a type from another crate that does have an impl. This case
// is checked for in `evaluate_stack` (and hence users
// who might care about this case, like coherence, should use
// that function).
if candidates.is_empty() {
// If there's an error type, 'downgrade' our result from
// `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
// emitting additional spurious errors, since we're guaranteed
// to have emitted at least one.
if stack.obligation.predicate.references_error() {
debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous");
return Ok(None);
}
return Err(Unimplemented);
}
// Just one candidate left.
self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation)
}
///////////////////////////////////////////////////////////////////////////
// EVALUATION
//
@ -2140,6 +2344,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
Ok(substs) => substs,
Err(()) => {
// FIXME: A rematch may fail when a candidate cache hit occurs
// on thefreshened form of the trait predicate, but the match
// fails for some reason that is not captured in the freshened
// cache key. For example, equating an impl trait ref against
// the placeholder trait ref may fail due the Generalizer relation
// raising a CyclicalTy error due to a sub_root_var relation
// for a variable being generalized...
self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
&format!(

View file

@ -77,7 +77,7 @@ use super::Utf8Error;
/// let sparkle_heart = [240, 159, 146, 150];
///
/// // We know these bytes are valid, so just use `unwrap()`.
/// let sparkle_heart = str::from_utf8(&sparkle_heart).unwrap();
/// let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap();
///
/// assert_eq!("💖", sparkle_heart);
/// ```

View file

@ -1463,6 +1463,30 @@ impl PathBuf {
true
}
/// Yields a mutable reference to the underlying [`OsString`] instance.
///
/// # Examples
///
/// ```
/// #![feature(path_as_mut_os_str)]
/// use std::path::{Path, PathBuf};
///
/// let mut path = PathBuf::from("/foo");
///
/// path.push("bar");
/// assert_eq!(path, Path::new("/foo/bar"));
///
/// // OsString's `push` does not add a separator.
/// path.as_mut_os_string().push("baz");
/// assert_eq!(path, Path::new("/foo/barbaz"));
/// ```
#[unstable(feature = "path_as_mut_os_str", issue = "105021")]
#[must_use]
#[inline]
pub fn as_mut_os_string(&mut self) -> &mut OsString {
&mut self.inner
}
/// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
///
/// # Examples
@ -1993,6 +2017,28 @@ impl Path {
&self.inner
}
/// Yields a mutable reference to the underlying [`OsStr`] slice.
///
/// # Examples
///
/// ```
/// #![feature(path_as_mut_os_str)]
/// use std::path::{Path, PathBuf};
///
/// let mut path = PathBuf::from("/Foo.TXT").into_boxed_path();
///
/// assert_ne!(&*path, Path::new("/foo.txt"));
///
/// path.as_mut_os_str().make_ascii_lowercase();
/// assert_eq!(&*path, Path::new("/foo.txt"));
/// ```
#[unstable(feature = "path_as_mut_os_str", issue = "105021")]
#[must_use]
#[inline]
pub fn as_mut_os_str(&mut self) -> &mut OsStr {
&mut self.inner
}
/// Yields a [`&str`] slice if the `Path` is valid unicode.
///
/// This conversion may entail doing a check for UTF-8 validity.

View file

@ -1,10 +1,8 @@
use crate::convert::TryFrom;
use crate::ffi::{CStr, CString, OsString};
use crate::ffi::{CStr, OsString};
use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::io::{self, Error, ErrorKind};
use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
use crate::os::unix::ffi::OsStrExt;
use crate::path::{Path, PathBuf};
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::cvt;

View file

@ -5,6 +5,7 @@ use crate::ffi::CStr;
use crate::io;
use crate::mem;
use crate::num::NonZeroUsize;
use crate::ptr;
use crate::sys::hermit::abi;
use crate::sys::hermit::thread_local_dtor::run_dtors;
use crate::time::Duration;
@ -47,7 +48,7 @@ impl Thread {
extern "C" fn thread_start(main: usize) {
unsafe {
// Finally, let's run some code.
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
Box::from_raw(ptr::from_exposed_addr::<Box<dyn FnOnce()>>(main).cast_mut())();
// run all destructors
run_dtors();

View file

@ -441,6 +441,7 @@ class RustBuild(object):
self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
lib_dir = "{}/lib".format(bin_root)
for lib in os.listdir(lib_dir):
if lib.endswith(".so"):

View file

@ -360,6 +360,7 @@ impl Config {
self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
self.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc"));
self.fix_bin_or_dylib(&bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"));
let lib_dir = bin_root.join("lib");
for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
let lib = t!(lib);

View file

@ -214,7 +214,7 @@ target | std | host | notes
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
[`aarch64-unknown-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS |
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS |
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
@ -305,7 +305,7 @@ target | std | host | notes
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
[`x86_64-pc-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS |
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS |
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support
`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos

View file

@ -93,15 +93,15 @@ Run the following:
```bash
env \
CC_aarch64-unknown-nto-qnx7.1.0="qcc" \
CFLAGS_aarch64-unknown-nto-qnx7.1.0="-Vgcc_ntoaarch64le_cxx" \
CXX_aarch64-unknown-nto-qnx7.1.0="qcc" \
AR_aarch64_unknown_nto_qnx7.1.0="ntoaarch64-ar" \
CC_x86_64-pc-nto-qnx7.1.0="qcc" \
CFLAGS_x86_64-pc-nto-qnx7.1.0="-Vgcc_ntox86_64_cxx" \
CXX_x86_64-pc-nto-qnx7.1.0="qcc" \
AR_x86_64_pc_nto_qnx7.1.0="ntox86_64-ar" \
./x.py build --target aarch64-unknown-nto-qnx7.1.0 --target x86_64-pc-nto-qnx7.1.0 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
CC_aarch64-unknown-nto-qnx710="qcc" \
CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \
CXX_aarch64-unknown-nto-qnx710="qcc" \
AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \
CC_x86_64-pc-nto-qnx710="qcc" \
CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \
CXX_x86_64-pc-nto-qnx710="qcc" \
AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \
./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
```
## Building Rust programs

View file

@ -158,6 +158,8 @@ approved by the appropriate team for that shared code before acceptance.
the name of the target makes people extremely likely to form incorrect
beliefs about what it targets, the name should be changed or augmented to
disambiguate it.
- If possible, use only letters, numbers, dashes and underscores for the name.
Periods (`.`) are known to cause issues in Cargo.
- Tier 3 targets may have unusual requirements to build or use, but must not
create legal issues or impose onerous legal terms for the Rust project or for
Rust developers or users.

View file

@ -1511,13 +1511,11 @@ details.rustdoc-toggle > summary.hideme > span {
}
details.rustdoc-toggle > summary::before {
background-image: url("toggle-plus-1092eb4930d581b0.svg");
background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left;
content: "";
cursor: pointer;
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-position: top left;
display: inline-block;
vertical-align: middle;
opacity: .5;
@ -1598,11 +1596,9 @@ details.rustdoc-toggle[open] > summary.hideme > span {
details.rustdoc-toggle[open] > summary::before,
details.rustdoc-toggle[open] > summary.hideme::before {
background-image: url("toggle-minus-31bbd6e4c77f5c96.svg");
background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left;
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-position: top left;
display: inline-block;
content: "";
}

View file

@ -0,0 +1,20 @@
// needs-asm-support
// compile-flags: -Ccodegen-units=1 -Zprint-mono-items=lazy --crate-type=lib
#[inline(always)]
pub unsafe fn f() {
//~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External]
static S: usize = 1;
//~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External]
fn fun() {}
core::arch::asm!("/* {0} {1} */", sym S, sym fun);
}
//~ MONO_ITEM fn g @@ asm_sym-cgu.0[External]
pub unsafe fn g() {
//~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal]
static S: usize = 2;
//~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal]
fn fun() {}
core::arch::asm!("/* {0} {1} */", sym S, sym fun);
}

View file

@ -0,0 +1,25 @@
// check-pass
#![feature(type_alias_impl_trait)]
trait Callable {
type Output;
fn call() -> Self::Output;
}
impl<'a> Callable for &'a () {
type Output = impl Sized;
fn call() -> Self::Output {}
}
fn test<'a>() -> impl Sized {
<&'a () as Callable>::call()
}
fn want_static<T: 'static>(_: T) {}
fn test2<'a>() {
want_static(<&'a () as Callable>::call());
}
fn main() {}

View file

@ -0,0 +1,38 @@
#![feature(type_alias_impl_trait)]
trait Callable {
type Output;
fn call(x: Self) -> Self::Output;
}
trait PlusOne {
fn plus_one(&mut self);
}
impl<'a> PlusOne for &'a mut i32 {
fn plus_one(&mut self) {
**self += 1;
}
}
impl<T: PlusOne> Callable for T {
type Output = impl PlusOne;
fn call(t: T) -> Self::Output { t }
}
fn test<'a>(y: &'a mut i32) -> impl PlusOne {
<&'a mut i32 as Callable>::call(y)
//~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
}
fn main() {
let mut z = 42;
let mut thing = test(&mut z);
let mut thing2 = test(&mut z);
thing.plus_one();
assert_eq!(z, 43);
thing2.plus_one();
assert_eq!(z, 44);
thing.plus_one();
assert_eq!(z, 45);
}

View file

@ -0,0 +1,16 @@
error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
--> $DIR/imply_bounds_from_bounds_param.rs:24:5
|
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
| -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
LL | <&'a mut i32 as Callable>::call(y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound
|
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a {
| ++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0700`.

View file

@ -0,0 +1,38 @@
// check-pass
#![feature(type_alias_impl_trait)]
fn foo() {
struct Foo<'a> {
x: &'a mut u8,
}
impl<'a> Foo<'a> {
fn foo(&self) -> impl Sized {}
}
// use site
let mut x = 5;
let y = Foo { x: &mut x };
let z = y.foo();
let _a = &x; // invalidate the `&'a mut`in `y`
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
}
fn bar() {
struct Foo<'a> {
x: &'a mut u8,
}
// desugared
type FooX<'a> = impl Sized;
impl<'a> Foo<'a> {
fn foo(&self) -> FooX<'a> {}
}
// use site
let mut x = 5;
let y = Foo { x: &mut x };
let z = y.foo();
let _a = &x; // invalidate the `&'a mut`in `y`
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
}
fn main() {}

View file

@ -44,7 +44,23 @@ fn main() {
target, filename, src
);
}
if !missing.is_empty() || !extra.is_empty() {
// Check target names for unwanted characters like `.` that can cause problems e.g. in Cargo.
// See also Tier 3 target policy.
// If desired, target names can ignore this check.
let ignore_target_names =
vec!["thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf"];
let mut invalid_target_name_found = false;
for target in &target_list {
if !ignore_target_names.contains(target)
&& !target.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
{
invalid_target_name_found = true;
eprintln!(
"error: Target name `{target}` contains other characters than ASCII alphanumeric (a-z, A-Z, 0-9), dash (-) or underscore (_)."
);
}
}
if !missing.is_empty() || !extra.is_empty() || invalid_target_name_found {
std::process::exit(1);
}
}