1
Fork 0

Auto merge of #112102 - Nilstrieb:rollup-ivu1hmc, r=Nilstrieb

Rollup of 7 pull requests

Successful merges:

 - #107916 (fix comment on Allocator trait)
 - #111543 (Uplift `clippy::invalid_utf8_in_unchecked` lint)
 - #111872 (fix: dedup `static_candidates` before report)
 - #111955 (bootstrap: Various Step refactors)
 - #112060 (`EarlyBinder::new` -> `EarlyBinder::bind`)
 - #112064 (Migrate GUI colors test to original CSS color format)
 - #112100 (Don't typecheck recovered method call from suggestion)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-05-30 13:25:42 +00:00
commit a9251b6ce1
82 changed files with 798 additions and 436 deletions

View file

@ -361,7 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
self.instance.subst_mir_and_normalize_erasing_regions( self.instance.subst_mir_and_normalize_erasing_regions(
self.tcx, self.tcx,
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
ty::EarlyBinder::new(value), ty::EarlyBinder::bind(value),
) )
} }

View file

@ -93,7 +93,7 @@ fn make_mir_scope<'ll, 'tcx>(
let callee = cx.tcx.subst_and_normalize_erasing_regions( let callee = cx.tcx.subst_and_normalize_erasing_regions(
instance.substs, instance.substs,
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
ty::EarlyBinder::new(callee), ty::EarlyBinder::bind(callee),
); );
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
cx.dbg_scope_fn(callee, callee_fn_abi, None) cx.dbg_scope_fn(callee, callee_fn_abi, None)

View file

@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.instance.subst_mir_and_normalize_erasing_regions( self.instance.subst_mir_and_normalize_erasing_regions(
self.cx.tcx(), self.cx.tcx(),
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
ty::EarlyBinder::new(value), ty::EarlyBinder::bind(value),
) )
} }
} }

View file

@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
.try_subst_mir_and_normalize_erasing_regions( .try_subst_mir_and_normalize_erasing_regions(
*self.tcx, *self.tcx,
self.param_env, self.param_env,
ty::EarlyBinder::new(value), ty::EarlyBinder::bind(value),
) )
.map_err(|_| err_inval!(TooGeneric)) .map_err(|_| err_inval!(TooGeneric))
} }

View file

@ -1280,7 +1280,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// params (and trait ref's late bound params). This logic is very similar to // params (and trait ref's late bound params). This logic is very similar to
// `Predicate::subst_supertrait`, and it's no coincidence why. // `Predicate::subst_supertrait`, and it's no coincidence why.
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
let subst_output = ty::EarlyBinder::new(shifted_output).subst(tcx, substs); let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs);
let bound_vars = tcx.late_bound_vars(binding.hir_id); let bound_vars = tcx.late_bound_vars(binding.hir_id);
ty::Binder::bind_with_vars(subst_output, bound_vars) ty::Binder::bind_with_vars(subst_output, bound_vars)

View file

@ -796,14 +796,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
}) })
}); });
debug!(%ty); debug!(%ty);
collected_tys.insert(def_id, ty::EarlyBinder::new(ty)); collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
} }
Err(err) => { Err(err) => {
let reported = tcx.sess.delay_span_bug( let reported = tcx.sess.delay_span_bug(
return_span, return_span,
format!("could not fully resolve: {ty} => {err:?}"), format!("could not fully resolve: {ty} => {err:?}"),
); );
collected_tys.insert(def_id, ty::EarlyBinder::new(tcx.ty_error(reported))); collected_tys.insert(def_id, ty::EarlyBinder::bind(tcx.ty_error(reported)));
} }
} }
} }

View file

@ -128,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only // We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization // substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself. // can occur on top of what has been done in the param_env query itself.
let param_env = ty::EarlyBinder::new(tcx.param_env(adt_def_id)) let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
.subst(tcx, adt_to_impl_substs) .subst(tcx, adt_to_impl_substs)
.with_constness(tcx.constness(drop_impl_def_id)); .with_constness(tcx.constness(drop_impl_def_id));

View file

@ -1407,7 +1407,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
} }
let mut param_count = CountParams::default(); let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break(); let has_region = pred.visit_with(&mut param_count).is_break();
let substituted_pred = ty::EarlyBinder::new(pred).subst(tcx, substs); let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes) // Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params. // or preds with multiple params.
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region

View file

@ -1124,7 +1124,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
bug!("unexpected sort of node in fn_sig(): {:?}", x); bug!("unexpected sort of node in fn_sig(): {:?}", x);
} }
}; };
ty::EarlyBinder::new(output) ty::EarlyBinder::bind(output)
} }
fn infer_return_ty_for_fn_sig<'tcx>( fn infer_return_ty_for_fn_sig<'tcx>(
@ -1312,7 +1312,7 @@ fn impl_trait_ref(
check_impl_constness(tcx, impl_.constness, ast_trait_ref), check_impl_constness(tcx, impl_.constness, ast_trait_ref),
) )
}) })
.map(ty::EarlyBinder::new) .map(ty::EarlyBinder::bind)
} }
fn check_impl_constness( fn check_impl_constness(

View file

@ -86,7 +86,7 @@ pub(super) fn explicit_item_bounds(
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
let opaque_ty = item.expect_opaque_ty(); let opaque_ty = item.expect_opaque_ty();
return ty::EarlyBinder::new(opaque_type_bounds( return ty::EarlyBinder::bind(opaque_type_bounds(
tcx, tcx,
opaque_def_id.expect_local(), opaque_def_id.expect_local(),
opaque_ty.bounds, opaque_ty.bounds,
@ -124,7 +124,7 @@ pub(super) fn explicit_item_bounds(
} }
_ => bug!("item_bounds called on {:?}", def_id), _ => bug!("item_bounds called on {:?}", def_id),
}; };
ty::EarlyBinder::new(bounds) ty::EarlyBinder::bind(bounds)
} }
pub(super) fn item_bounds( pub(super) fn item_bounds(

View file

@ -323,7 +323,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
return map[&assoc_item.trait_item_def_id.unwrap()]; return map[&assoc_item.trait_item_def_id.unwrap()];
} }
Err(_) => { Err(_) => {
return ty::EarlyBinder::new(tcx.ty_error_with_message( return ty::EarlyBinder::bind(tcx.ty_error_with_message(
DUMMY_SP, DUMMY_SP,
"Could not collect return position impl trait in trait tys", "Could not collect return position impl trait in trait tys",
)); ));
@ -497,7 +497,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
bug!("unexpected sort of node in type_of(): {:?}", x); bug!("unexpected sort of node in type_of(): {:?}", x);
} }
}; };
ty::EarlyBinder::new(output) ty::EarlyBinder::bind(output)
} }
fn infer_placeholder_type<'a>( fn infer_placeholder_type<'a>(

View file

@ -68,7 +68,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
} }
} }
ty::EarlyBinder::new(required_predicates) ty::EarlyBinder::bind(required_predicates)
}) })
} }
} }

View file

@ -74,7 +74,7 @@ pub(super) fn infer_predicates(
if item_required_predicates.len() > item_predicates_len { if item_required_predicates.len() > item_predicates_len {
predicates_added = true; predicates_added = true;
global_inferred_outlives global_inferred_outlives
.insert(item_did.to_def_id(), ty::EarlyBinder::new(item_required_predicates)); .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates));
} }
} }

View file

@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod) .steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
{ {
// Try suggesting `foo(a)` -> `a.foo()` if possible. // Try suggesting `foo(a)` -> `a.foo()` if possible.
if let Some(ty) =
self.suggest_call_as_method( self.suggest_call_as_method(
&mut diag, &mut diag,
segment, segment,
arg_exprs, arg_exprs,
call_expr, call_expr,
expected expected
) );
{
diag.emit(); diag.emit();
return ty;
} else {
diag.emit();
}
} }
let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
@ -496,9 +490,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>], arg_exprs: &'tcx [hir::Expr<'tcx>],
call_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
) -> Option<Ty<'tcx>> { ) {
if let [callee_expr, rest @ ..] = arg_exprs { if let [callee_expr, rest @ ..] = arg_exprs {
let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?; let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else {
return;
};
// First, do a probe with `IsSuggestion(true)` to avoid emitting // First, do a probe with `IsSuggestion(true)` to avoid emitting
// any strange errors. If it's successful, then we'll do a true // any strange errors. If it's successful, then we'll do a true
@ -513,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ProbeScope::AllTraits, ProbeScope::AllTraits,
expected.only_has_type(self), expected.only_has_type(self),
) else { ) else {
return None; return;
}; };
let pick = self.confirm_method( let pick = self.confirm_method(
@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment, segment,
); );
if pick.illegal_sized_bound.is_some() { if pick.illegal_sized_bound.is_some() {
return None; return;
} }
let up_to_rcvr_span = segment.ident.span.until(callee_expr.span); let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg, sugg,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
// Let's check the method fully now
let return_ty = self.check_method_argument_types(
segment.ident.span,
call_expr,
Ok(pick.callee),
rest,
TupleArgumentsFlag::DontTupleArguments,
expected,
);
return Some(return_ty);
} }
} }
None
} }
fn report_invalid_callee( fn report_invalid_callee(

View file

@ -473,6 +473,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut custom_span_label = false; let mut custom_span_label = false;
let static_candidates = &mut no_match_data.static_candidates; let static_candidates = &mut no_match_data.static_candidates;
// `static_candidates` may have same candidates appended by
// inherent and extension, which may result in incorrect
// diagnostic.
static_candidates.dedup();
if !static_candidates.is_empty() { if !static_candidates.is_empty() {
err.note( err.note(
"found the following associated functions; to be used as methods, \ "found the following associated functions; to be used as methods, \

View file

@ -304,6 +304,14 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
lint_improper_ctypes_union_layout_reason = this union has unspecified layout lint_improper_ctypes_union_layout_reason = this union has unspecified layout
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
lint_lintpass_by_hand = implementing `LintPass` by hand lint_lintpass_by_hand = implementing `LintPass` by hand
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead

View file

@ -0,0 +1,118 @@
use std::str::Utf8Error;
use rustc_ast::{BorrowKind, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
use crate::lints::InvalidFromUtf8Diag;
use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `invalid_from_utf8_unchecked` lint checks for calls to
/// `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`
/// with an invalid UTF-8 literal.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #[allow(unused)]
/// unsafe {
/// std::str::from_utf8_unchecked(b"Ru\x82st");
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Creating such a `str` would result in undefined behavior as per documentation
/// for `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`.
pub INVALID_FROM_UTF8_UNCHECKED,
Deny,
"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"
}
declare_lint! {
/// The `invalid_from_utf8` lint checks for calls to
/// `std::str::from_utf8` and `std::str::from_utf8_mut`
/// with an invalid UTF-8 literal.
///
/// ### Example
///
/// ```rust
/// # #[allow(unused)]
/// std::str::from_utf8(b"Ru\x82st");
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Trying to create such a `str` would always return an error as per documentation
/// for `std::str::from_utf8` and `std::str::from_utf8_mut`.
pub INVALID_FROM_UTF8,
Warn,
"using a non UTF-8 literal in `std::str::from_utf8`"
}
declare_lint_pass!(InvalidFromUtf8 => [INVALID_FROM_UTF8_UNCHECKED, INVALID_FROM_UTF8]);
impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Call(path, [arg]) = expr.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
&& [sym::str_from_utf8, sym::str_from_utf8_mut,
sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item)
{
let lint = |utf8_error: Utf8Error| {
let label = arg.span;
let method = diag_item.as_str().strip_prefix("str_").unwrap();
let method = format!("std::str::{method}");
let valid_up_to = utf8_error.valid_up_to();
let is_unchecked_variant = diag_item.as_str().contains("unchecked");
cx.emit_spanned_lint(
if is_unchecked_variant { INVALID_FROM_UTF8_UNCHECKED } else { INVALID_FROM_UTF8 },
expr.span,
if is_unchecked_variant {
InvalidFromUtf8Diag::Unchecked { method, valid_up_to, label }
} else {
InvalidFromUtf8Diag::Checked { method, valid_up_to, label }
}
)
};
match &arg.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => {
if let LitKind::ByteStr(bytes, _) = &lit
&& let Err(utf8_error) = std::str::from_utf8(bytes)
{
lint(utf8_error);
}
},
ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
let elements = args.iter().map(|e|{
match &e.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
LitKind::Byte(b) => Some(*b),
LitKind::Int(b, _) => Some(*b as u8),
_ => None
}
_ => None
}
}).collect::<Option<Vec<_>>>();
if let Some(elements) = elements
&& let Err(utf8_error) = std::str::from_utf8(&elements)
{
lint(utf8_error);
}
}
_ => {}
}
}
}
}

View file

@ -60,6 +60,7 @@ mod expect;
mod for_loops_over_fallibles; mod for_loops_over_fallibles;
pub mod hidden_unicode_codepoints; pub mod hidden_unicode_codepoints;
mod internal; mod internal;
mod invalid_from_utf8;
mod late; mod late;
mod let_underscore; mod let_underscore;
mod levels; mod levels;
@ -102,6 +103,7 @@ use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
use for_loops_over_fallibles::*; use for_loops_over_fallibles::*;
use hidden_unicode_codepoints::*; use hidden_unicode_codepoints::*;
use internal::*; use internal::*;
use invalid_from_utf8::*;
use let_underscore::*; use let_underscore::*;
use map_unit_fn::*; use map_unit_fn::*;
use methods::*; use methods::*;
@ -207,6 +209,7 @@ late_lint_methods!(
HardwiredLints: HardwiredLints, HardwiredLints: HardwiredLints,
ImproperCTypesDeclarations: ImproperCTypesDeclarations, ImproperCTypesDeclarations: ImproperCTypesDeclarations,
ImproperCTypesDefinitions: ImproperCTypesDefinitions, ImproperCTypesDefinitions: ImproperCTypesDefinitions,
InvalidFromUtf8: InvalidFromUtf8,
VariantSizeDifferences: VariantSizeDifferences, VariantSizeDifferences: VariantSizeDifferences,
BoxPointers: BoxPointers, BoxPointers: BoxPointers,
PathStatements: PathStatements, PathStatements: PathStatements,

View file

@ -699,6 +699,25 @@ pub struct ForgetCopyDiag<'a> {
pub label: Span, pub label: Span,
} }
// invalid_from_utf8.rs
#[derive(LintDiagnostic)]
pub enum InvalidFromUtf8Diag {
#[diag(lint_invalid_from_utf8_unchecked)]
Unchecked {
method: String,
valid_up_to: usize,
#[label]
label: Span,
},
#[diag(lint_invalid_from_utf8_checked)]
Checked {
method: String,
valid_up_to: usize,
#[label]
label: Span,
},
}
// hidden_unicode_codepoints.rs // hidden_unicode_codepoints.rs
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(lint_hidden_unicode_codepoints)] #[diag(lint_hidden_unicode_codepoints)]

View file

@ -858,7 +858,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
} else { } else {
tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
}; };
ty::EarlyBinder::new(&*output) ty::EarlyBinder::bind(&*output)
} }
fn get_variant( fn get_variant(

View file

@ -1730,7 +1730,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
ty::Closure(_, substs) => { ty::Closure(_, substs) => {
let constness = self.tcx.constness(def_id.to_def_id()); let constness = self.tcx.constness(def_id.to_def_id());
self.tables.constness.set_some(def_id.to_def_id().index, constness); self.tables.constness.set_some(def_id.to_def_id().index, constness);
record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder::new(substs.as_closure().sig())); record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder::bind(substs.as_closure().sig()));
} }
_ => bug!("closure that is neither generator nor closure"), _ => bug!("closure that is neither generator nor closure"),

View file

@ -476,7 +476,7 @@ impl<'tcx> Body<'tcx> {
/// Returns the return type; it always return first element from `local_decls` array. /// Returns the return type; it always return first element from `local_decls` array.
#[inline] #[inline]
pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> { pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder::new(self.local_decls[RETURN_PLACE].ty) ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
} }
/// Gets the location of the terminator for the given block. /// Gets the location of the terminator for the given block.

View file

@ -573,7 +573,7 @@ impl<'tcx> AdtDef<'tcx> {
/// Due to normalization being eager, this applies even if /// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299). /// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> { pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
ty::EarlyBinder::new(tcx.adt_sized_constraint(self.did())) ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
} }
} }

View file

@ -254,5 +254,5 @@ pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBind
"`const_param_default` expected a generic parameter with a constant" "`const_param_default` expected a generic parameter with a constant"
), ),
}; };
ty::EarlyBinder::new(Const::from_anon_const(tcx, default_def_id)) ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
} }

View file

@ -343,7 +343,7 @@ impl<'tcx> GenericPredicates<'tcx> {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
{ {
EarlyBinder::new(self.predicates).subst_iter_copied(tcx, substs) EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
} }
#[instrument(level = "debug", skip(self, tcx))] #[instrument(level = "debug", skip(self, tcx))]
@ -358,7 +358,7 @@ impl<'tcx> GenericPredicates<'tcx> {
} }
instantiated instantiated
.predicates .predicates
.extend(self.predicates.iter().map(|(p, _)| EarlyBinder::new(*p).subst(tcx, substs))); .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs)));
instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
} }

View file

@ -158,7 +158,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> { fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
match self { match self {
Self::ConstIsZero(c) => { Self::ConstIsZero(c) => {
let c = ty::EarlyBinder::new(c).subst(tcx, substs); let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
let pred = match c.kind().try_to_target_usize(tcx) { let pred = match c.kind().try_to_target_usize(tcx) {
Some(0) => Self::True, Some(0) => Self::True,
Some(1..) => Self::False, Some(1..) => Self::False,
@ -167,7 +167,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(pred) Some(pred)
} }
Self::GenericType(t) => { Self::GenericType(t) => {
Some(ty::EarlyBinder::new(t).subst(tcx, substs).inhabited_predicate(tcx)) Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
} }
Self::And(&[a, b]) => match a.subst_opt(tcx, substs) { Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)), None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),

View file

@ -764,7 +764,7 @@ impl<'tcx> Predicate<'tcx> {
let shifted_pred = let shifted_pred =
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
let new = EarlyBinder::new(shifted_pred).subst(tcx, trait_ref.skip_binder().substs); let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b] // 3) ['x] + ['b] -> ['x, 'b]
let bound_vars = let bound_vars =
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));

View file

@ -568,7 +568,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
let layout = tcx.generator_layout(def_id).unwrap(); let layout = tcx.generator_layout(def_id).unwrap();
layout.variant_fields.iter().map(move |variant| { layout.variant_fields.iter().map(move |variant| {
variant.iter().map(move |field| { variant.iter().map(move |field| {
ty::EarlyBinder::new(layout.field_tys[*field].ty).subst(tcx, self.substs) ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs)
}) })
}) })
} }

View file

@ -545,7 +545,7 @@ impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<T> EarlyBinder<T> { impl<T> EarlyBinder<T> {
pub fn new(inner: T) -> EarlyBinder<T> { pub fn bind(inner: T) -> EarlyBinder<T> {
EarlyBinder(inner) EarlyBinder(inner)
} }

View file

@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
.as_ref() .as_ref()
.map_or_else(|| [].iter(), |l| l.field_tys.iter()) .map_or_else(|| [].iter(), |l| l.field_tys.iter())
.filter(|decl| !decl.ignore_for_traits) .filter(|decl| !decl.ignore_for_traits)
.map(|decl| ty::EarlyBinder::new(decl.ty)) .map(|decl| ty::EarlyBinder::bind(decl.ty))
} }
/// Normalizes all opaque types in the given value, replacing them /// Normalizes all opaque types in the given value, replacing them

View file

@ -96,13 +96,13 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> { impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self { fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
ty::EarlyBinder::new(Ty::from_cycle_error(tcx, cycle)) ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle))
} }
} }
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> { impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self { fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
ty::EarlyBinder::new(ty::Binder::from_cycle_error(tcx, cycle)) ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle))
} }
} }

View file

@ -83,7 +83,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
// If the inner type matches the type bound by `Pointer` // If the inner type matches the type bound by `Pointer`
if inner_ty == bound_ty { if inner_ty == bound_ty {
// Do a substitution using the parameters from the callsite // Do a substitution using the parameters from the callsite
let subst_ty = EarlyBinder::new(inner_ty).subst(self.tcx, substs_ref); let subst_ty = EarlyBinder::bind(inner_ty).subst(self.tcx, substs_ref);
if let Some((fn_id, fn_substs)) = if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(subst_ty) FunctionItemRefChecker::is_fn_ref(subst_ty)
{ {

View file

@ -192,7 +192,7 @@ impl<'tcx> Inliner<'tcx> {
let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions( let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions(
self.tcx, self.tcx,
self.param_env, self.param_env,
ty::EarlyBinder::new(callee_body.clone()), ty::EarlyBinder::bind(callee_body.clone()),
) else { ) else {
return Err("failed to normalize callee body"); return Err("failed to normalize callee body");
}; };
@ -455,7 +455,7 @@ impl<'tcx> Inliner<'tcx> {
// If the place doesn't actually need dropping, treat it like a regular goto. // If the place doesn't actually need dropping, treat it like a regular goto.
let ty = callsite let ty = callsite
.callee .callee
.subst_mir(self.tcx, ty::EarlyBinder::new(&place.ty(callee_body, tcx).ty)); .subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty));
if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind { if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
work_list.push(unwind); work_list.push(unwind);
} }
@ -790,7 +790,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
// If the place doesn't actually need dropping, treat it like a regular goto. // If the place doesn't actually need dropping, treat it like a regular goto.
let ty = self let ty = self
.instance .instance
.subst_mir(tcx, ty::EarlyBinder::new(&place.ty(self.callee_body, tcx).ty)); .subst_mir(tcx, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty));
if ty.needs_drop(tcx, self.param_env) { if ty.needs_drop(tcx, self.param_env) {
self.cost += CALL_PENALTY; self.cost += CALL_PENALTY;
if let UnwindAction::Cleanup(_) = unwind { if let UnwindAction::Cleanup(_) = unwind {
@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
} }
} }
TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::new(&f.literal.ty())); let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.literal.ty()));
self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
// Don't give intrinsics the extra penalty for calls // Don't give intrinsics the extra penalty for calls
INSTR_COST INSTR_COST

View file

@ -47,7 +47,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions( let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(
tcx, tcx,
param_env, param_env,
ty::EarlyBinder::new(substs), ty::EarlyBinder::bind(substs),
) else { ) else {
trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping"); trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping");
continue; continue;

View file

@ -69,7 +69,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
// of this function. Is this intentional? // of this function. Is this intentional?
if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(Ty::kind) { if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(Ty::kind) {
let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap(); let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
let body = EarlyBinder::new(body.clone()).subst(tcx, substs); let body = EarlyBinder::bind(body.clone()).subst(tcx, substs);
debug!("make_shim({:?}) = {:?}", instance, body); debug!("make_shim({:?}) = {:?}", instance, body);
return body; return body;
} }

View file

@ -677,7 +677,7 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
self.instance.subst_mir_and_normalize_erasing_regions( self.instance.subst_mir_and_normalize_erasing_regions(
self.tcx, self.tcx,
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),
ty::EarlyBinder::new(value), ty::EarlyBinder::bind(value),
) )
} }
} }

View file

@ -29,12 +29,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
let before_feature_tys = tcx.subst_and_normalize_erasing_regions( let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
closure_instance.substs, closure_instance.substs,
param_env, param_env,
ty::EarlyBinder::new(before_feature_tys), ty::EarlyBinder::bind(before_feature_tys),
); );
let after_feature_tys = tcx.subst_and_normalize_erasing_regions( let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
closure_instance.substs, closure_instance.substs,
param_env, param_env,
ty::EarlyBinder::new(after_feature_tys), ty::EarlyBinder::bind(after_feature_tys),
); );
let new_size = tcx let new_size = tcx

View file

@ -1454,6 +1454,10 @@ symbols! {
stop_after_dataflow, stop_after_dataflow,
store, store,
str, str,
str_from_utf8,
str_from_utf8_mut,
str_from_utf8_unchecked,
str_from_utf8_unchecked_mut,
str_split_whitespace, str_split_whitespace,
str_trim, str_trim,
str_trim_end, str_trim_end,

View file

@ -274,7 +274,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id); let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id);
if !substs.is_empty() { if !substs.is_empty() {
param_env = EarlyBinder::new(param_env).subst(self.tcx, substs); param_env = EarlyBinder::bind(param_env).subst(self.tcx, substs);
} }
match &mut impl_trait_ref { match &mut impl_trait_ref {

View file

@ -487,7 +487,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
tcx, tcx,
ObligationCause::dummy_with_span(*span), ObligationCause::dummy_with_span(*span),
param_env, param_env,
ty::EarlyBinder::new(*pred).subst(tcx, impl_trait_ref.substs), ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
) )
}) })
}); });

View file

@ -642,7 +642,7 @@ fn receiver_for_self_ty<'tcx>(
if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) } if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
}); });
let result = EarlyBinder::new(receiver_ty).subst(tcx, substs); let result = EarlyBinder::bind(receiver_ty).subst(tcx, substs);
debug!( debug!(
"receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}", "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
receiver_ty, self_ty, method_def_id, result receiver_ty, self_ty, method_def_id, result

View file

@ -307,13 +307,13 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
// there, but that needs some way to handle cycles. // there, but that needs some way to handle cycles.
constraints constraints
.dtorck_types .dtorck_types
.extend(dtorck_types.iter().map(|t| EarlyBinder::new(*t).subst(tcx, substs))); .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
constraints constraints
.outlives .outlives
.extend(outlives.iter().map(|t| EarlyBinder::new(*t).subst(tcx, substs))); .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
constraints constraints
.overflows .overflows
.extend(overflows.iter().map(|t| EarlyBinder::new(*t).subst(tcx, substs))); .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
} }
// Objects must be alive in order for their destructor // Objects must be alive in order for their destructor

View file

@ -301,7 +301,7 @@ fn associated_type_for_impl_trait_in_trait(
trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id)); trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
// Copy type_of of the opaque. // Copy type_of of the opaque.
trait_assoc_ty.type_of(ty::EarlyBinder::new(tcx.mk_opaque( trait_assoc_ty.type_of(ty::EarlyBinder::bind(tcx.mk_opaque(
opaque_ty_def_id.to_def_id(), opaque_ty_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
))); )));

View file

@ -419,7 +419,7 @@ pub fn thir_abstract_const(
let root_span = body.exprs[body_id].span; let root_span = body.exprs[body_id].span;
Ok(Some(ty::EarlyBinder::new(recurse_build(tcx, body, body_id, root_span)?))) Ok(Some(ty::EarlyBinder::bind(recurse_build(tcx, body, body_id, root_span)?)))
} }
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {

View file

@ -610,7 +610,7 @@ fn generator_layout<'tcx>(
) -> Result<Layout<'tcx>, LayoutError<'tcx>> { ) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
use SavedLocalEligibility::*; use SavedLocalEligibility::*;
let tcx = cx.tcx; let tcx = cx.tcx;
let subst_field = |ty: Ty<'tcx>| EarlyBinder::new(ty).subst(tcx, substs); let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs);
let Some(info) = tcx.generator_layout(def_id) else { let Some(info) = tcx.generator_layout(def_id) else {
return Err(LayoutError::Unknown(ty)); return Err(LayoutError::Unknown(ty));

View file

@ -210,7 +210,7 @@ fn drop_tys_helper<'tcx>(
match subty.kind() { match subty.kind() {
ty::Adt(adt_id, subst) => { ty::Adt(adt_id, subst) => {
for subty in tcx.adt_drop_tys(adt_id.did())? { for subty in tcx.adt_drop_tys(adt_id.did())? {
vec.push(EarlyBinder::new(subty).subst(tcx, subst)); vec.push(EarlyBinder::bind(subty).subst(tcx, subst));
} }
} }
_ => vec.push(subty), _ => vec.push(subty),

View file

@ -507,7 +507,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
if self_ty_matches { if self_ty_matches {
debug!("issue33140_self_ty - MATCHES!"); debug!("issue33140_self_ty - MATCHES!");
Some(EarlyBinder::new(self_ty)) Some(EarlyBinder::bind(self_ty))
} else { } else {
debug!("issue33140_self_ty - non-matching self type"); debug!("issue33140_self_ty - non-matching self type");
None None

View file

@ -1,3 +1,5 @@
#![cfg_attr(not(bootstrap), allow(invalid_from_utf8))]
use std::assert_matches::assert_matches; use std::assert_matches::assert_matches;
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::Ordering::{Equal, Greater, Less}; use std::cmp::Ordering::{Equal, Greater, Less};

View file

@ -94,8 +94,9 @@ impl fmt::Display for AllocError {
/// ///
/// # Safety /// # Safety
/// ///
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity /// * Memory blocks returned from an allocator that are [*currently allocated*] must point to
/// until the instance and all of its copies and clones are dropped, /// valid memory and retain their validity while they are [*currently allocated*] and at
/// least one of the instance and all of its clones has not been dropped.
/// ///
/// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this /// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this
/// allocator. A copied or cloned allocator must behave like the same allocator, and /// allocator. A copied or cloned allocator must behave like the same allocator, and

View file

@ -84,6 +84,7 @@ use super::Utf8Error;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")] #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
#[rustc_allow_const_fn_unstable(str_internals)] #[rustc_allow_const_fn_unstable(str_internals)]
#[rustc_diagnostic_item = "str_from_utf8"]
pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
// FIXME: This should use `?` again, once it's `const` // FIXME: This should use `?` again, once it's `const`
match run_utf8_validation(v) { match run_utf8_validation(v) {
@ -127,6 +128,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
/// errors that can be returned. /// errors that can be returned.
#[stable(feature = "str_mut_extras", since = "1.20.0")] #[stable(feature = "str_mut_extras", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
#[rustc_diagnostic_item = "str_from_utf8_mut"]
pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
// This should use `?` again, once it's `const` // This should use `?` again, once it's `const`
match run_utf8_validation(v) { match run_utf8_validation(v) {
@ -167,6 +169,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
#[must_use] #[must_use]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")] #[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")]
#[rustc_diagnostic_item = "str_from_utf8_unchecked"]
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
// SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
// Also relies on `&str` and `&[u8]` having the same layout. // Also relies on `&str` and `&[u8]` having the same layout.
@ -194,6 +197,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
#[must_use] #[must_use]
#[stable(feature = "str_mut_extras", since = "1.20.0")] #[stable(feature = "str_mut_extras", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked_mut", issue = "91005")] #[rustc_const_unstable(feature = "const_str_from_utf8_unchecked_mut", issue = "91005")]
#[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"]
pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
// SAFETY: the caller must guarantee that the bytes `v` // SAFETY: the caller must guarantee that the bytes `v`
// are valid UTF-8, thus the cast to `*mut str` is safe. // are valid UTF-8, thus the cast to `*mut str` is safe.

View file

@ -103,11 +103,14 @@ impl RunConfig<'_> {
} }
/// Return a list of crate names selected by `run.paths`. /// Return a list of crate names selected by `run.paths`.
#[track_caller]
pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> { pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
let mut crates = Vec::new(); let mut crates = Vec::new();
for krate in &self.paths { for krate in &self.paths {
let path = krate.assert_single_path(); let path = krate.assert_single_path();
let crate_name = self.builder.crate_paths[&path.path]; let Some(crate_name) = self.builder.crate_paths.get(&path.path) else {
panic!("missing crate for path {}", path.path.display())
};
crates.push(crate_name.to_string()); crates.push(crate_name.to_string());
} }
INTERNER.intern_list(crates) INTERNER.intern_list(crates)
@ -427,25 +430,6 @@ impl<'a> ShouldRun<'a> {
} }
} }
/// Indicates it should run if the command-line selects the given crate or
/// any of its (local) dependencies.
///
/// Compared to `krate`, this treats the dependencies as aliases for the
/// same job. Generally it is preferred to use `krate`, and treat each
/// individual path separately. For example `./x.py test src/liballoc`
/// (which uses `krate`) will test just `liballoc`. However, `./x.py check
/// src/liballoc` (which uses `all_krates`) will check all of `libtest`.
/// `all_krates` should probably be removed at some point.
pub fn all_krates(mut self, name: &str) -> Self {
let mut set = BTreeSet::new();
for krate in self.builder.in_tree_crates(name, None) {
let path = krate.local_path(self.builder);
set.insert(TaskPath { path, kind: Some(self.kind) });
}
self.paths.insert(PathSet::Set(set));
self
}
/// Indicates it should run if the command-line selects the given crate or /// Indicates it should run if the command-line selects the given crate or
/// any of its (local) dependencies. /// any of its (local) dependencies.
/// ///
@ -458,6 +442,8 @@ impl<'a> ShouldRun<'a> {
/// Indicates it should run if the command-line selects any of the given crates. /// Indicates it should run if the command-line selects any of the given crates.
/// ///
/// `make_run` will be called a single time with all matching command-line paths. /// `make_run` will be called a single time with all matching command-line paths.
///
/// Prefer [`ShouldRun::crate_or_deps`] to this function where possible.
pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self { pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self {
for krate in crates { for krate in crates {
let path = krate.local_path(self.builder); let path = krate.local_path(self.builder);
@ -487,7 +473,15 @@ impl<'a> ShouldRun<'a> {
self.paths(&[path]) self.paths(&[path])
} }
// multiple aliases for the same job /// Multiple aliases for the same job.
///
/// This differs from [`path`] in that multiple calls to path will end up calling `make_run`
/// multiple times, whereas a single call to `paths` will only ever generate a single call to
/// `paths`.
///
/// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible.
///
/// [`path`]: ShouldRun::path
pub fn paths(mut self, paths: &[&str]) -> Self { pub fn paths(mut self, paths: &[&str]) -> Self {
static SUBMODULES_PATHS: OnceCell<Vec<String>> = OnceCell::new(); static SUBMODULES_PATHS: OnceCell<Vec<String>> = OnceCell::new();
@ -641,12 +635,16 @@ impl Kind {
} }
} }
pub fn test_description(&self) -> &'static str { pub fn description(&self) -> String {
match self { match self {
Kind::Test => "Testing", Kind::Test => "Testing",
Kind::Bench => "Benchmarking", Kind::Bench => "Benchmarking",
_ => panic!("not a test command: {}!", self.as_str()), Kind::Doc => "Documenting",
Kind::Run => "Running",
Kind::Suggest => "Suggesting",
_ => return format!("{self:?}"),
} }
.to_owned()
} }
} }

View file

@ -1,5 +1,6 @@
use super::*; use super::*;
use crate::config::{Config, DryRun, TargetSelection}; use crate::config::{Config, DryRun, TargetSelection};
use crate::doc::DocumentationFormat;
use std::thread; use std::thread;
fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
@ -66,6 +67,16 @@ macro_rules! std {
}; };
} }
macro_rules! doc_std {
($host:ident => $target:ident, stage = $stage:literal) => {
doc::Std::new(
$stage,
TargetSelection::from_user(stringify!($target)),
DocumentationFormat::HTML,
)
};
}
macro_rules! rustc { macro_rules! rustc {
($host:ident => $target:ident, stage = $stage:literal) => { ($host:ident => $target:ident, stage = $stage:literal) => {
compile::Rustc::new( compile::Rustc::new(
@ -144,6 +155,9 @@ fn alias_and_path_for_library() {
first(cache.all::<compile::Std>()), first(cache.all::<compile::Std>()),
&[std!(A => A, stage = 0), std!(A => A, stage = 1)] &[std!(A => A, stage = 0), std!(A => A, stage = 1)]
); );
let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A"], &["A"]));
assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
} }
#[test] #[test]

View file

@ -1,8 +1,10 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes. //! Implementation of compiling the compiler and standard library, in "check"-based modes.
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::builder::{crate_description, Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned; use crate::cache::Interned;
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo}; use crate::compile::{
add_to_sysroot, make_run_crates, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
};
use crate::config::TargetSelection; use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType}; use crate::tool::{prepare_tool_cargo, SourceType};
use crate::INTERNER; use crate::INTERNER;
@ -12,6 +14,12 @@ use std::path::{Path, PathBuf};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std { pub struct Std {
pub target: TargetSelection, pub target: TargetSelection,
/// Whether to build only a subset of crates.
///
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
///
/// [`compile::Rustc`]: crate::compile::Rustc
crates: Interned<Vec<String>>,
} }
/// Returns args for the subcommand itself (not for cargo) /// Returns args for the subcommand itself (not for cargo)
@ -66,16 +74,23 @@ fn cargo_subcommand(kind: Kind) -> &'static str {
} }
} }
impl Std {
pub fn new(target: TargetSelection) -> Self {
Self { target, crates: INTERNER.intern_list(vec![]) }
}
}
impl Step for Std { impl Step for Std {
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.all_krates("sysroot").path("library") run.crate_or_deps("sysroot").path("library")
} }
fn make_run(run: RunConfig<'_>) { fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Std { target: run.target }); let crates = make_run_crates(&run, "library");
run.builder.ensure(Std { target: run.target, crates });
} }
fn run(self, builder: &Builder<'_>) { fn run(self, builder: &Builder<'_>) {
@ -97,7 +112,14 @@ impl Step for Std {
cargo.arg("--lib"); cargo.arg("--lib");
} }
let _guard = builder.msg_check("library artifacts", target); for krate in &*self.crates {
cargo.arg("-p").arg(krate);
}
let _guard = builder.msg_check(
format_args!("library artifacts{}", crate_description(&self.crates)),
target,
);
run_cargo( run_cargo(
builder, builder,
cargo, cargo,
@ -117,7 +139,8 @@ impl Step for Std {
} }
// don't run on std twice with x.py clippy // don't run on std twice with x.py clippy
if builder.kind == Kind::Clippy { // don't check test dependencies if we haven't built libtest
if builder.kind == Kind::Clippy || !self.crates.is_empty() {
return; return;
} }
@ -147,8 +170,8 @@ impl Step for Std {
// Explicitly pass -p for all dependencies krates -- this will force cargo // Explicitly pass -p for all dependencies krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather // to also check the tests/benches/examples for these crates, rather
// than just the leaf crate. // than just the leaf crate.
for krate in builder.in_tree_crates("test", Some(target)) { for krate in &*self.crates {
cargo.arg("-p").arg(krate.name); cargo.arg("-p").arg(krate);
} }
let _guard = builder.msg_check("library test/bench/example targets", target); let _guard = builder.msg_check("library test/bench/example targets", target);
@ -167,6 +190,22 @@ impl Step for Std {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc { pub struct Rustc {
pub target: TargetSelection, pub target: TargetSelection,
/// Whether to build only a subset of crates.
///
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
///
/// [`compile::Rustc`]: crate::compile::Rustc
crates: Interned<Vec<String>>,
}
impl Rustc {
pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
let mut crates = vec![];
for krate in builder.in_tree_crates("rustc-main", None) {
crates.push(krate.name.to_string());
}
Self { target, crates: INTERNER.intern_list(crates) }
}
} }
impl Step for Rustc { impl Step for Rustc {
@ -175,11 +214,12 @@ impl Step for Rustc {
const DEFAULT: bool = true; const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.all_krates("rustc-main").path("compiler") run.crate_or_deps("rustc-main").path("compiler")
} }
fn make_run(run: RunConfig<'_>) { fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustc { target: run.target }); let crates = make_run_crates(&run, "compiler");
run.builder.ensure(Rustc { target: run.target, crates });
} }
/// Builds the compiler. /// Builds the compiler.
@ -200,7 +240,7 @@ impl Step for Rustc {
builder.ensure(crate::compile::Std::new(compiler, compiler.host)); builder.ensure(crate::compile::Std::new(compiler, compiler.host));
builder.ensure(crate::compile::Std::new(compiler, target)); builder.ensure(crate::compile::Std::new(compiler, target));
} else { } else {
builder.ensure(Std { target }); builder.ensure(Std::new(target));
} }
let mut cargo = builder.cargo( let mut cargo = builder.cargo(
@ -218,14 +258,17 @@ impl Step for Rustc {
cargo.arg("--all-targets"); cargo.arg("--all-targets");
} }
// Explicitly pass -p for all compiler krates -- this will force cargo // Explicitly pass -p for all compiler crates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather // to also check the tests/benches/examples for these crates, rather
// than just the leaf crate. // than just the leaf crate.
for krate in builder.in_tree_crates("rustc-main", Some(target)) { for krate in &*self.crates {
cargo.arg("-p").arg(krate.name); cargo.arg("-p").arg(krate);
} }
let _guard = builder.msg_check("compiler artifacts", target); let _guard = builder.msg_check(
format_args!("compiler artifacts{}", crate_description(&self.crates)),
target,
);
run_cargo( run_cargo(
builder, builder,
cargo, cargo,
@ -268,7 +311,7 @@ impl Step for CodegenBackend {
let target = self.target; let target = self.target;
let backend = self.backend; let backend = self.backend;
builder.ensure(Rustc { target }); builder.ensure(Rustc::new(target, builder));
let mut cargo = builder.cargo( let mut cargo = builder.cargo(
compiler, compiler,
@ -318,7 +361,7 @@ impl Step for RustAnalyzer {
let compiler = builder.compiler(builder.top_stage, builder.config.build); let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target; let target = self.target;
builder.ensure(Std { target }); builder.ensure(Std::new(target));
let mut cargo = prepare_tool_cargo( let mut cargo = prepare_tool_cargo(
builder, builder,
@ -386,7 +429,7 @@ macro_rules! tool_check_step {
let compiler = builder.compiler(builder.top_stage, builder.config.build); let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target; let target = self.target;
builder.ensure(Rustc { target }); builder.ensure(Rustc::new(target, builder));
let mut cargo = prepare_tool_cargo( let mut cargo = prepare_tool_cargo(
builder, builder,

View file

@ -48,6 +48,17 @@ impl Std {
} }
} }
/// Given an `alias` selected by the `Step` and the paths passed on the command line,
/// return a list of the crates that should be built.
///
/// Normally, people will pass *just* `library` if they pass it.
/// But it's possible (although strange) to pass something like `library std core`.
/// Build all crates anyway, as if they hadn't passed the other args.
pub(crate) fn make_run_crates(run: &RunConfig<'_>, alias: &str) -> Interned<Vec<String>> {
let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias));
if has_alias { Default::default() } else { run.cargo_crates_in_set() }
}
impl Step for Std { impl Step for Std {
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -62,16 +73,10 @@ impl Step for Std {
} }
fn make_run(run: RunConfig<'_>) { fn make_run(run: RunConfig<'_>) {
// Normally, people will pass *just* library if they pass it.
// But it's possible (although strange) to pass something like `library std core`.
// Build all crates anyway, as if they hadn't passed the other args.
let has_library =
run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() };
run.builder.ensure(Std { run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
target: run.target, target: run.target,
crates, crates: make_run_crates(&run, "library"),
}); });
} }
@ -615,6 +620,8 @@ impl Step for Rustc {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let mut crates = run.builder.in_tree_crates("rustc-main", None); let mut crates = run.builder.in_tree_crates("rustc-main", None);
for (i, krate) in crates.iter().enumerate() { for (i, krate) in crates.iter().enumerate() {
// We can't allow `build rustc` as an alias for this Step, because that's reserved by `Assemble`.
// Ideally Assemble would use `build compiler` instead, but that seems too confusing to be worth the breaking change.
if krate.name == "rustc-main" { if krate.name == "rustc-main" {
crates.swap_remove(i); crates.swap_remove(i);
break; break;

View file

@ -106,11 +106,7 @@ impl Step for JsonDocs {
/// Builds the `rust-docs-json` installer component. /// Builds the `rust-docs-json` installer component.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let host = self.host; let host = self.host;
builder.ensure(crate::doc::Std { builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON));
stage: builder.top_stage,
target: host,
format: DocumentationFormat::JSON,
});
let dest = "share/doc/rust/json"; let dest = "share/doc/rust/json";

View file

@ -7,7 +7,6 @@
//! Everything here is basically just a shim around calling either `rustbook` or //! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`. //! `rustdoc`.
use std::ffi::OsStr;
use std::fs; use std::fs;
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -16,6 +15,7 @@ use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER}; use crate::cache::{Interned, INTERNER};
use crate::compile; use crate::compile;
use crate::compile::make_run_crates;
use crate::config::{Config, TargetSelection}; use crate::config::{Config, TargetSelection};
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
use crate::util::{symlink_dir, t, up_to_date}; use crate::util::{symlink_dir, t, up_to_date};
@ -87,15 +87,6 @@ book!(
StyleGuide, "src/doc/style-guide", "style-guide"; StyleGuide, "src/doc/style-guide", "style-guide";
); );
// "library/std" -> ["library", "std"]
//
// Used for deciding whether a particular step is one requested by the user on
// the `x.py doc` command line, which determines whether `--open` will open that
// page.
pub(crate) fn components_simplified(path: &PathBuf) -> Vec<&str> {
path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct UnstableBook { pub struct UnstableBook {
target: TargetSelection, target: TargetSelection,
@ -425,11 +416,18 @@ impl Step for SharedAssets {
} }
} }
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Std { pub struct Std {
pub stage: u32, pub stage: u32,
pub target: TargetSelection, pub target: TargetSelection,
pub format: DocumentationFormat, pub format: DocumentationFormat,
crates: Interned<Vec<String>>,
}
impl Std {
pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
Std { stage, target, format, crates: INTERNER.intern_list(vec![]) }
}
} }
impl Step for Std { impl Step for Std {
@ -438,7 +436,7 @@ impl Step for Std {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder; let builder = run.builder;
run.all_krates("sysroot").path("library").default_condition(builder.config.docs) run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs)
} }
fn make_run(run: RunConfig<'_>) { fn make_run(run: RunConfig<'_>) {
@ -450,6 +448,7 @@ impl Step for Std {
} else { } else {
DocumentationFormat::HTML DocumentationFormat::HTML
}, },
crates: make_run_crates(&run, "library"),
}); });
} }
@ -457,7 +456,7 @@ impl Step for Std {
/// ///
/// This will generate all documentation for the standard library and its /// This will generate all documentation for the standard library and its
/// dependencies. This is largely just a wrapper around `cargo doc`. /// dependencies. This is largely just a wrapper around `cargo doc`.
fn run(self, builder: &Builder<'_>) { fn run(mut self, builder: &Builder<'_>) {
let stage = self.stage; let stage = self.stage;
let target = self.target; let target = self.target;
let out = match self.format { let out = match self.format {
@ -471,41 +470,24 @@ impl Step for Std {
builder.ensure(SharedAssets { target: self.target }); builder.ensure(SharedAssets { target: self.target });
} }
let index_page = builder.src.join("src/doc/index.md").into_os_string(); let index_page = builder
.src
.join("src/doc/index.md")
.into_os_string()
.into_string()
.expect("non-utf8 paths are unsupported");
let mut extra_args = match self.format { let mut extra_args = match self.format {
DocumentationFormat::HTML => vec![ DocumentationFormat::HTML => {
OsStr::new("--markdown-css"), vec!["--markdown-css", "rust.css", "--markdown-no-toc", "--index-page", &index_page]
OsStr::new("rust.css"), }
OsStr::new("--markdown-no-toc"), DocumentationFormat::JSON => vec!["--output-format", "json"],
OsStr::new("--index-page"),
&index_page,
],
DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")],
}; };
if !builder.config.docs_minification { if !builder.config.docs_minification {
extra_args.push(OsStr::new("--disable-minification")); extra_args.push("--disable-minification");
} }
let requested_crates = builder doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
.paths
.iter()
.map(components_simplified)
.filter_map(|path| {
if path.len() >= 2 && path.get(0) == Some(&"library") {
// single crate
Some(path[1].to_owned())
} else if !path.is_empty() {
// ??
Some(path[0].to_owned())
} else {
// all library crates
None
}
})
.collect::<Vec<_>>();
doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates);
// Don't open if the format is json // Don't open if the format is json
if let DocumentationFormat::JSON = self.format { if let DocumentationFormat::JSON = self.format {
@ -514,7 +496,11 @@ impl Step for Std {
// Look for library/std, library/core etc in the `x.py doc` arguments and // Look for library/std, library/core etc in the `x.py doc` arguments and
// open the corresponding rendered docs. // open the corresponding rendered docs.
for requested_crate in requested_crates { if self.crates.is_empty() {
self.crates = INTERNER.intern_list(vec!["library".to_owned()]);
};
for requested_crate in &*self.crates {
if requested_crate == "library" { if requested_crate == "library" {
// For `x.py doc library --open`, open `std` by default. // For `x.py doc library --open`, open `std` by default.
let index = out.join("std").join("index.html"); let index = out.join("std").join("index.html");
@ -538,7 +524,7 @@ impl Step for Std {
/// or remote link. /// or remote link.
const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"]; const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum DocumentationFormat { pub enum DocumentationFormat {
HTML, HTML,
JSON, JSON,
@ -563,24 +549,22 @@ fn doc_std(
stage: u32, stage: u32,
target: TargetSelection, target: TargetSelection,
out: &Path, out: &Path,
extra_args: &[&OsStr], extra_args: &[&str],
requested_crates: &[String], requested_crates: &[String],
) { ) {
builder.info(&format!(
"Documenting{} stage{} library ({}) in {} format",
crate_description(requested_crates),
stage,
target,
format.as_str()
));
if builder.no_std(target) == Some(true) { if builder.no_std(target) == Some(true) {
panic!( panic!(
"building std documentation for no_std target {target} is not supported\n\ "building std documentation for no_std target {target} is not supported\n\
Set `docs = false` in the config to disable documentation." Set `docs = false` in the config to disable documentation, or pass `--exclude doc::library`."
); );
} }
let compiler = builder.compiler(stage, builder.config.build); let compiler = builder.compiler(stage, builder.config.build);
let description =
format!("library{} in {} format", crate_description(&requested_crates), format.as_str());
let _guard = builder.msg(Kind::Doc, stage, &description, compiler.host, target);
let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" };
let target_dir = let target_dir =
builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name); builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name);
@ -590,35 +574,42 @@ fn doc_std(
// as a function parameter. // as a function parameter.
let out_dir = target_dir.join(target.triple).join("doc"); let out_dir = target_dir.join(target.triple).join("doc");
let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "doc");
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
compile::std_cargo(builder, target, compiler.stage, &mut cargo); compile::std_cargo(builder, target, compiler.stage, &mut cargo);
cargo cargo
.arg("--no-deps")
.arg("--target-dir") .arg("--target-dir")
.arg(&*target_dir.to_string_lossy()) .arg(&*target_dir.to_string_lossy())
.arg("-p")
.arg(package)
.arg("-Zskip-rustdoc-fingerprint") .arg("-Zskip-rustdoc-fingerprint")
.arg("--") .rustdocflag("-Z")
.arg("-Z") .rustdocflag("unstable-options")
.arg("unstable-options") .rustdocflag("--resource-suffix")
.arg("--resource-suffix") .rustdocflag(&builder.version);
.arg(&builder.version) for arg in extra_args {
.args(extra_args); cargo.rustdocflag(arg);
if builder.config.library_docs_private_items {
cargo.arg("--document-private-items").arg("--document-hidden-items");
} }
builder.run(&mut cargo.into());
if builder.config.library_docs_private_items {
cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items");
}
// HACK: because we use `--manifest-path library/sysroot/Cargo.toml`, cargo thinks we only want to document that specific crate, not its dependencies.
// Override its default.
let built_crates = if requested_crates.is_empty() {
builder
.in_tree_crates("sysroot", None)
.into_iter()
.map(|krate| krate.name.to_string())
.collect()
} else {
requested_crates.to_vec()
}; };
for krate in STD_PUBLIC_CRATES { for krate in built_crates {
run_cargo_rustdoc_for(krate); cargo.arg("-p").arg(krate);
if requested_crates.iter().any(|p| p == krate) {
// No need to document more of the libraries if we have the one we want.
break;
}
} }
builder.run(&mut cargo.into());
builder.cp_r(&out_dir, &out); builder.cp_r(&out_dir, &out);
} }
@ -626,6 +617,28 @@ fn doc_std(
pub struct Rustc { pub struct Rustc {
pub stage: u32, pub stage: u32,
pub target: TargetSelection, pub target: TargetSelection,
crates: Interned<Vec<String>>,
}
impl Rustc {
pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self {
// Find dependencies for top level crates.
let root_crates = vec![
INTERNER.intern_str("rustc_driver"),
INTERNER.intern_str("rustc_codegen_llvm"),
INTERNER.intern_str("rustc_codegen_ssa"),
];
let crates: Vec<_> = root_crates
.iter()
.flat_map(|krate| {
builder
.in_tree_crates(krate, Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
})
.collect();
Self { stage, target, crates: INTERNER.intern_list(crates) }
}
} }
impl Step for Rustc { impl Step for Rustc {
@ -641,7 +654,11 @@ impl Step for Rustc {
} }
fn make_run(run: RunConfig<'_>) { fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target }); run.builder.ensure(Rustc {
stage: run.builder.top_stage,
target: run.target,
crates: make_run_crates(&run, "compiler"),
});
} }
/// Generates compiler documentation. /// Generates compiler documentation.
@ -654,15 +671,6 @@ impl Step for Rustc {
let stage = self.stage; let stage = self.stage;
let target = self.target; let target = self.target;
let paths = builder
.paths
.iter()
.filter(|path| {
let components = components_simplified(path);
components.len() >= 2 && components[0] == "compiler"
})
.collect::<Vec<_>>();
// This is the intended out directory for compiler documentation. // This is the intended out directory for compiler documentation.
let out = builder.compiler_doc_out(target); let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
@ -672,7 +680,13 @@ impl Step for Rustc {
let compiler = builder.compiler(stage, builder.config.build); let compiler = builder.compiler(stage, builder.config.build);
builder.ensure(compile::Std::new(compiler, builder.config.build)); builder.ensure(compile::Std::new(compiler, builder.config.build));
builder.info(&format!("Documenting stage{} compiler ({})", stage, target)); let _guard = builder.msg(
Kind::Doc,
stage,
&format!("compiler{}", crate_description(&self.crates)),
compiler.host,
target,
);
// This uses a shared directory so that librustdoc documentation gets // This uses a shared directory so that librustdoc documentation gets
// correctly built and merged with the rustc documentation. This is // correctly built and merged with the rustc documentation. This is
@ -710,22 +724,8 @@ impl Step for Rustc {
cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("--extern-html-root-url");
cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
let root_crates = if paths.is_empty() {
vec![
INTERNER.intern_str("rustc_driver"),
INTERNER.intern_str("rustc_codegen_llvm"),
INTERNER.intern_str("rustc_codegen_ssa"),
]
} else {
paths.into_iter().map(|p| builder.crate_paths[p]).collect()
};
// Find dependencies for top level crates.
let compiler_crates = root_crates.iter().flat_map(|krate| {
builder.in_tree_crates(krate, Some(target)).into_iter().map(|krate| krate.name)
});
let mut to_open = None; let mut to_open = None;
for krate in compiler_crates { for krate in &*self.crates {
// Create all crate output directories first to make sure rustdoc uses // Create all crate output directories first to make sure rustdoc uses
// relative links. // relative links.
// FIXME: Cargo should probably do this itself. // FIXME: Cargo should probably do this itself.
@ -785,7 +785,7 @@ macro_rules! tool_doc {
if true $(&& $rustc_tool)? { if true $(&& $rustc_tool)? {
// Build rustc docs so that we generate relative links. // Build rustc docs so that we generate relative links.
builder.ensure(Rustc { stage, target }); builder.ensure(Rustc::new(stage, target, builder));
// Rustdoc needs the rustc sysroot available to build. // Rustdoc needs the rustc sysroot available to build.
// FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed

View file

@ -1020,8 +1020,8 @@ impl Build {
host: impl Into<Option<TargetSelection>>, host: impl Into<Option<TargetSelection>>,
target: impl Into<Option<TargetSelection>>, target: impl Into<Option<TargetSelection>>,
) -> Option<gha::Group> { ) -> Option<gha::Group> {
let action = action.into(); let action = action.into().description();
let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}"); let msg = |fmt| format!("{action} stage{stage} {what}{fmt}");
let msg = if let Some(target) = target.into() { let msg = if let Some(target) = target.into() {
let host = host.into().unwrap(); let host = host.into().unwrap();
if host == target { if host == target {

View file

@ -101,7 +101,7 @@ impl Step for CrateBootstrap {
); );
builder.info(&format!( builder.info(&format!(
"{} {} stage0 ({})", "{} {} stage0 ({})",
builder.kind.test_description(), builder.kind.description(),
path, path,
bootstrap_host, bootstrap_host,
)); ));
@ -220,7 +220,7 @@ impl Step for HtmlCheck {
} }
// Ensure that a few different kinds of documentation are available. // Ensure that a few different kinds of documentation are available.
builder.default_doc(&[]); builder.default_doc(&[]);
builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage }); builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))); try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
} }
@ -886,11 +886,11 @@ impl Step for RustdocJSStd {
command.arg("--test-file").arg(path); command.arg("--test-file").arg(path);
} }
} }
builder.ensure(crate::doc::Std { builder.ensure(crate::doc::Std::new(
target: self.target, builder.top_stage,
stage: builder.top_stage, self.target,
format: DocumentationFormat::HTML, DocumentationFormat::HTML,
}); ));
builder.run(&mut command); builder.run(&mut command);
} else { } else {
builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests"); builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests");

View file

@ -40,7 +40,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id); let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
let impl_ty = ty.subst(infcx.tcx, substs); let impl_ty = ty.subst(infcx.tcx, substs);
let param_env = EarlyBinder::new(param_env).subst(infcx.tcx, substs); let param_env = EarlyBinder::bind(param_env).subst(infcx.tcx, substs);
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs); let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);

View file

@ -212,7 +212,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO, crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
crate::int_plus_one::INT_PLUS_ONE_INFO, crate::int_plus_one::INT_PLUS_ONE_INFO,
crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO, crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO,
crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO, crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO, crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO, crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,

View file

@ -1219,7 +1219,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
return false; return false;
} }
let predicate = EarlyBinder::new(predicate).subst(cx.tcx, &substs_with_referent_ty); let predicate = EarlyBinder::bind(predicate).subst(cx.tcx, &substs_with_referent_ty);
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
infcx.predicate_must_hold_modulo_regions(&obligation) infcx.predicate_must_hold_modulo_regions(&obligation)

View file

@ -243,7 +243,7 @@ fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, substs
| ty::Ref(..) | ty::Ref(..)
| ty::Slice(_) | ty::Slice(_)
| ty::Tuple(_) => { | ty::Tuple(_) => {
format!("<{}>", EarlyBinder::new(ty).subst(cx.tcx, substs)) format!("<{}>", EarlyBinder::bind(ty).subst(cx.tcx, substs))
}, },
_ => ty.to_string(), _ => ty.to_string(),
} }

View file

@ -1,74 +0,0 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{match_function_call, paths};
use rustc_ast::{BorrowKind, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
/// Checks for `std::str::from_utf8_unchecked` with an invalid UTF-8 literal
///
/// ### Why is this bad?
/// Creating such a `str` would result in undefined behavior
///
/// ### Example
/// ```rust
/// # #[allow(unused)]
/// unsafe {
/// std::str::from_utf8_unchecked(b"cl\x82ippy");
/// }
/// ```
#[clippy::version = "1.64.0"]
pub INVALID_UTF8_IN_UNCHECKED,
correctness,
"using a non UTF-8 literal in `std::std::from_utf8_unchecked`"
}
declare_lint_pass!(InvalidUtf8InUnchecked => [INVALID_UTF8_IN_UNCHECKED]);
impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
match &arg.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => {
if let LitKind::ByteStr(bytes, _) = &lit
&& std::str::from_utf8(bytes).is_err()
{
lint(cx, expr.span);
}
},
ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
let elements = args.iter().map(|e|{
match &e.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
LitKind::Byte(b) => Some(*b),
#[allow(clippy::cast_possible_truncation)]
LitKind::Int(b, _) => Some(*b as u8),
_ => None
}
_ => None
}
}).collect::<Option<Vec<_>>>();
if let Some(elements) = elements
&& std::str::from_utf8(&elements).is_err()
{
lint(cx, expr.span);
}
}
_ => {}
}
}
}
}
fn lint(cx: &LateContext<'_>, span: Span) {
span_lint(
cx,
INVALID_UTF8_IN_UNCHECKED,
span,
"non UTF-8 literal in `std::str::from_utf8_unchecked`",
);
}

View file

@ -157,7 +157,6 @@ mod inline_fn_without_body;
mod instant_subtraction; mod instant_subtraction;
mod int_plus_one; mod int_plus_one;
mod invalid_upcast_comparisons; mod invalid_upcast_comparisons;
mod invalid_utf8_in_unchecked;
mod items_after_statements; mod items_after_statements;
mod items_after_test_module; mod items_after_test_module;
mod iter_not_returning_iterator; mod iter_not_returning_iterator;
@ -937,7 +936,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default()); store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv()))); store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));

View file

@ -241,7 +241,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
&& let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs) && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
&& let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
{ {
item_ty == EarlyBinder::new(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id)) item_ty == EarlyBinder::bind(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id))
} else { } else {
false false
} }

View file

@ -428,7 +428,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
})); }));
if trait_predicates.any(|predicate| { if trait_predicates.any(|predicate| {
let predicate = EarlyBinder::new(predicate).subst(cx.tcx, new_subst); let predicate = EarlyBinder::bind(predicate).subst(cx.tcx, new_subst);
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
!cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation) !cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
}) { }) {
@ -438,7 +438,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
let output_ty = fn_sig.output(); let output_ty = fn_sig.output();
if output_ty.contains(*param_ty) { if output_ty.contains(*param_ty) {
if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions( if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions(
new_subst, cx.param_env, EarlyBinder::new(output_ty)) { new_subst, cx.param_env, EarlyBinder::bind(output_ty)) {
expr = parent_expr; expr = parent_expr;
ty = new_ty; ty = new_ty;
continue; continue;

View file

@ -43,6 +43,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::into_iter_on_array", "array_into_iter"), ("clippy::into_iter_on_array", "array_into_iter"),
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"), ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
("clippy::invalid_ref", "invalid_value"), ("clippy::invalid_ref", "invalid_value"),
("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"),
("clippy::let_underscore_drop", "let_underscore_drop"), ("clippy::let_underscore_drop", "let_underscore_drop"),
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"), ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
("clippy::panic_params", "non_fmt_panics"), ("clippy::panic_params", "non_fmt_panics"),

View file

@ -462,7 +462,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
let substs = if self.substs.is_empty() { let substs = if self.substs.is_empty() {
substs substs
} else { } else {
EarlyBinder::new(substs).subst(self.lcx.tcx, self.substs) EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs)
}; };
let result = self let result = self

View file

@ -1,20 +0,0 @@
#![warn(clippy::invalid_utf8_in_unchecked)]
fn main() {
// Valid
unsafe {
std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]);
std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']);
std::str::from_utf8_unchecked(b"clippy");
let x = 0xA0;
std::str::from_utf8_unchecked(&[0xC0, x]);
}
// Invalid
unsafe {
std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
std::str::from_utf8_unchecked(b"cl\x82ippy");
}
}

View file

@ -1,22 +0,0 @@
error: non UTF-8 literal in `std::str::from_utf8_unchecked`
--> $DIR/invalid_utf8_in_unchecked.rs:16:9
|
LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::invalid-utf8-in-unchecked` implied by `-D warnings`
error: non UTF-8 literal in `std::str::from_utf8_unchecked`
--> $DIR/invalid_utf8_in_unchecked.rs:17:9
|
LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'/x82', b'i', b'p', b'p', b'y']);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: non UTF-8 literal in `std::str::from_utf8_unchecked`
--> $DIR/invalid_utf8_in_unchecked.rs:18:9
|
LL | std::str::from_utf8_unchecked(b"cl/x82ippy");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors

View file

@ -38,6 +38,7 @@
#![allow(array_into_iter)] #![allow(array_into_iter)]
#![allow(invalid_atomic_ordering)] #![allow(invalid_atomic_ordering)]
#![allow(invalid_value)] #![allow(invalid_value)]
#![allow(invalid_from_utf8_unchecked)]
#![allow(let_underscore_drop)] #![allow(let_underscore_drop)]
#![allow(enum_intrinsics_non_enums)] #![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)] #![allow(non_fmt_panics)]
@ -87,6 +88,7 @@
#![warn(array_into_iter)] #![warn(array_into_iter)]
#![warn(invalid_atomic_ordering)] #![warn(invalid_atomic_ordering)]
#![warn(invalid_value)] #![warn(invalid_value)]
#![warn(invalid_from_utf8_unchecked)]
#![warn(let_underscore_drop)] #![warn(let_underscore_drop)]
#![warn(enum_intrinsics_non_enums)] #![warn(enum_intrinsics_non_enums)]
#![warn(non_fmt_panics)] #![warn(non_fmt_panics)]

View file

@ -38,6 +38,7 @@
#![allow(array_into_iter)] #![allow(array_into_iter)]
#![allow(invalid_atomic_ordering)] #![allow(invalid_atomic_ordering)]
#![allow(invalid_value)] #![allow(invalid_value)]
#![allow(invalid_from_utf8_unchecked)]
#![allow(let_underscore_drop)] #![allow(let_underscore_drop)]
#![allow(enum_intrinsics_non_enums)] #![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)] #![allow(non_fmt_panics)]
@ -87,6 +88,7 @@
#![warn(clippy::into_iter_on_array)] #![warn(clippy::into_iter_on_array)]
#![warn(clippy::invalid_atomic_ordering)] #![warn(clippy::invalid_atomic_ordering)]
#![warn(clippy::invalid_ref)] #![warn(clippy::invalid_ref)]
#![warn(clippy::invalid_utf8_in_unchecked)]
#![warn(clippy::let_underscore_drop)] #![warn(clippy::let_underscore_drop)]
#![warn(clippy::mem_discriminant_non_enum)] #![warn(clippy::mem_discriminant_non_enum)]
#![warn(clippy::panic_params)] #![warn(clippy::panic_params)]

View file

@ -1,5 +1,5 @@
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
--> $DIR/rename.rs:49:9 --> $DIR/rename.rs:50:9
| |
LL | #![warn(clippy::almost_complete_letter_range)] LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@ -7,286 +7,292 @@ LL | #![warn(clippy::almost_complete_letter_range)]
= note: `-D renamed-and-removed-lints` implied by `-D warnings` = note: `-D renamed-and-removed-lints` implied by `-D warnings`
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
--> $DIR/rename.rs:50:9 --> $DIR/rename.rs:51:9
| |
LL | #![warn(clippy::blacklisted_name)] LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
--> $DIR/rename.rs:51:9 --> $DIR/rename.rs:52:9
| |
LL | #![warn(clippy::block_in_if_condition_expr)] LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
--> $DIR/rename.rs:52:9 --> $DIR/rename.rs:53:9
| |
LL | #![warn(clippy::block_in_if_condition_stmt)] LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
--> $DIR/rename.rs:53:9 --> $DIR/rename.rs:54:9
| |
LL | #![warn(clippy::box_vec)] LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
--> $DIR/rename.rs:54:9 --> $DIR/rename.rs:55:9
| |
LL | #![warn(clippy::const_static_lifetime)] LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
--> $DIR/rename.rs:55:9 --> $DIR/rename.rs:56:9
| |
LL | #![warn(clippy::cyclomatic_complexity)] LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
--> $DIR/rename.rs:56:9 --> $DIR/rename.rs:57:9
| |
LL | #![warn(clippy::derive_hash_xor_eq)] LL | #![warn(clippy::derive_hash_xor_eq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
--> $DIR/rename.rs:57:9 --> $DIR/rename.rs:58:9
| |
LL | #![warn(clippy::disallowed_method)] LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
--> $DIR/rename.rs:58:9 --> $DIR/rename.rs:59:9
| |
LL | #![warn(clippy::disallowed_type)] LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
--> $DIR/rename.rs:59:9 --> $DIR/rename.rs:60:9
| |
LL | #![warn(clippy::eval_order_dependence)] LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
--> $DIR/rename.rs:60:9 --> $DIR/rename.rs:61:9
| |
LL | #![warn(clippy::identity_conversion)] LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
--> $DIR/rename.rs:61:9 --> $DIR/rename.rs:62:9
| |
LL | #![warn(clippy::if_let_some_result)] LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
--> $DIR/rename.rs:62:9 --> $DIR/rename.rs:63:9
| |
LL | #![warn(clippy::integer_arithmetic)] LL | #![warn(clippy::integer_arithmetic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
--> $DIR/rename.rs:63:9 --> $DIR/rename.rs:64:9
| |
LL | #![warn(clippy::logic_bug)] LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
--> $DIR/rename.rs:64:9 --> $DIR/rename.rs:65:9
| |
LL | #![warn(clippy::new_without_default_derive)] LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
--> $DIR/rename.rs:65:9 --> $DIR/rename.rs:66:9
| |
LL | #![warn(clippy::option_and_then_some)] LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
--> $DIR/rename.rs:66:9 --> $DIR/rename.rs:67:9
| |
LL | #![warn(clippy::option_expect_used)] LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
--> $DIR/rename.rs:67:9 --> $DIR/rename.rs:68:9
| |
LL | #![warn(clippy::option_map_unwrap_or)] LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> $DIR/rename.rs:68:9 --> $DIR/rename.rs:69:9
| |
LL | #![warn(clippy::option_map_unwrap_or_else)] LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
--> $DIR/rename.rs:69:9 --> $DIR/rename.rs:70:9
| |
LL | #![warn(clippy::option_unwrap_used)] LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
--> $DIR/rename.rs:70:9 --> $DIR/rename.rs:71:9
| |
LL | #![warn(clippy::ref_in_deref)] LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
--> $DIR/rename.rs:71:9 --> $DIR/rename.rs:72:9
| |
LL | #![warn(clippy::result_expect_used)] LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> $DIR/rename.rs:72:9 --> $DIR/rename.rs:73:9
| |
LL | #![warn(clippy::result_map_unwrap_or_else)] LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
--> $DIR/rename.rs:73:9 --> $DIR/rename.rs:74:9
| |
LL | #![warn(clippy::result_unwrap_used)] LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
--> $DIR/rename.rs:74:9 --> $DIR/rename.rs:75:9
| |
LL | #![warn(clippy::single_char_push_str)] LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
--> $DIR/rename.rs:75:9 --> $DIR/rename.rs:76:9
| |
LL | #![warn(clippy::stutter)] LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
--> $DIR/rename.rs:76:9 --> $DIR/rename.rs:77:9
| |
LL | #![warn(clippy::to_string_in_display)] LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
--> $DIR/rename.rs:77:9 --> $DIR/rename.rs:78:9
| |
LL | #![warn(clippy::zero_width_space)] LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
--> $DIR/rename.rs:78:9 --> $DIR/rename.rs:79:9
| |
LL | #![warn(clippy::clone_double_ref)] LL | #![warn(clippy::clone_double_ref)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
--> $DIR/rename.rs:79:9 --> $DIR/rename.rs:80:9
| |
LL | #![warn(clippy::drop_bounds)] LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
--> $DIR/rename.rs:80:9 --> $DIR/rename.rs:81:9
| |
LL | #![warn(clippy::drop_copy)] LL | #![warn(clippy::drop_copy)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
error: lint `clippy::drop_ref` has been renamed to `dropping_references` error: lint `clippy::drop_ref` has been renamed to `dropping_references`
--> $DIR/rename.rs:81:9 --> $DIR/rename.rs:82:9
| |
LL | #![warn(clippy::drop_ref)] LL | #![warn(clippy::drop_ref)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
--> $DIR/rename.rs:82:9 --> $DIR/rename.rs:83:9
| |
LL | #![warn(clippy::for_loop_over_option)] LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
--> $DIR/rename.rs:83:9 --> $DIR/rename.rs:84:9
| |
LL | #![warn(clippy::for_loop_over_result)] LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
--> $DIR/rename.rs:84:9 --> $DIR/rename.rs:85:9
| |
LL | #![warn(clippy::for_loops_over_fallibles)] LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
--> $DIR/rename.rs:85:9 --> $DIR/rename.rs:86:9
| |
LL | #![warn(clippy::forget_copy)] LL | #![warn(clippy::forget_copy)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
error: lint `clippy::forget_ref` has been renamed to `forgetting_references` error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
--> $DIR/rename.rs:86:9 --> $DIR/rename.rs:87:9
| |
LL | #![warn(clippy::forget_ref)] LL | #![warn(clippy::forget_ref)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
--> $DIR/rename.rs:87:9 --> $DIR/rename.rs:88:9
| |
LL | #![warn(clippy::into_iter_on_array)] LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
--> $DIR/rename.rs:88:9 --> $DIR/rename.rs:89:9
| |
LL | #![warn(clippy::invalid_atomic_ordering)] LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value` error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
--> $DIR/rename.rs:89:9 --> $DIR/rename.rs:90:9
| |
LL | #![warn(clippy::invalid_ref)] LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
--> $DIR/rename.rs:91:9
|
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
--> $DIR/rename.rs:90:9 --> $DIR/rename.rs:92:9
| |
LL | #![warn(clippy::let_underscore_drop)] LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
--> $DIR/rename.rs:91:9 --> $DIR/rename.rs:93:9
| |
LL | #![warn(clippy::mem_discriminant_non_enum)] LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
--> $DIR/rename.rs:92:9 --> $DIR/rename.rs:94:9
| |
LL | #![warn(clippy::panic_params)] LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
--> $DIR/rename.rs:93:9 --> $DIR/rename.rs:95:9
| |
LL | #![warn(clippy::positional_named_format_parameters)] LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
--> $DIR/rename.rs:94:9 --> $DIR/rename.rs:96:9
| |
LL | #![warn(clippy::temporary_cstring_as_ptr)] LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
--> $DIR/rename.rs:95:9 --> $DIR/rename.rs:97:9
| |
LL | #![warn(clippy::unknown_clippy_lints)] LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels` error: lint `clippy::unused_label` has been renamed to `unused_labels`
--> $DIR/rename.rs:96:9 --> $DIR/rename.rs:98:9
| |
LL | #![warn(clippy::unused_label)] LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: aborting due to 48 previous errors error: aborting due to 49 previous errors

View file

@ -25,11 +25,11 @@ call-function: ("check-style", {
}) })
call-function: ("check-style", { call-function: ("check-style", {
"theme": "dark", "theme": "dark",
"background": "rgb(73, 74, 61)", "background": "#494a3d",
"border": "rgb(187, 116, 16)", "border": "#bb7410",
}) })
call-function: ("check-style", { call-function: ("check-style", {
"theme": "light", "theme": "light",
"background": "rgb(253, 255, 211)", "background": "#fdffd3",
"border": "rgb(173, 124, 55)", "border": "#ad7c37",
}) })

View file

@ -0,0 +1,93 @@
// check-pass
#![feature(concat_bytes)]
#![warn(invalid_from_utf8_unchecked)]
#![warn(invalid_from_utf8)]
pub fn from_utf8_unchecked_mut() {
// Valid
unsafe {
std::str::from_utf8_unchecked_mut(&mut [99, 108, 105, 112, 112, 121]);
std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']);
let x = 0xA0;
std::str::from_utf8_unchecked_mut(&mut [0xC0, x]);
}
// Invalid
unsafe {
std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
//~^ WARN calls to `std::str::from_utf8_unchecked_mut`
std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
//~^ WARN calls to `std::str::from_utf8_unchecked_mut`
}
}
pub fn from_utf8_unchecked() {
// Valid
unsafe {
std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]);
std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']);
std::str::from_utf8_unchecked(b"clippy");
let x = 0xA0;
std::str::from_utf8_unchecked(&[0xC0, x]);
}
// Invalid
unsafe {
std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
//~^ WARN calls to `std::str::from_utf8_unchecked`
std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
//~^ WARN calls to `std::str::from_utf8_unchecked`
std::str::from_utf8_unchecked(b"cl\x82ippy");
//~^ WARN calls to `std::str::from_utf8_unchecked`
std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
//~^ WARN calls to `std::str::from_utf8_unchecked`
}
}
pub fn from_utf8_mut() {
// Valid
{
std::str::from_utf8_mut(&mut [99, 108, 105, 112, 112, 121]);
std::str::from_utf8_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']);
let x = 0xa0;
std::str::from_utf8_mut(&mut [0xc0, x]);
}
// Invalid
{
std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
//~^ WARN calls to `std::str::from_utf8_mut`
std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
//~^ WARN calls to `std::str::from_utf8_mut`
}
}
pub fn from_utf8() {
// Valid
{
std::str::from_utf8(&[99, 108, 105, 112, 112, 121]);
std::str::from_utf8(&[b'c', b'l', b'i', b'p', b'p', b'y']);
std::str::from_utf8(b"clippy");
let x = 0xA0;
std::str::from_utf8(&[0xC0, x]);
}
// Invalid
{
std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
//~^ WARN calls to `std::str::from_utf8`
std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
//~^ WARN calls to `std::str::from_utf8`
std::str::from_utf8(b"cl\x82ippy");
//~^ WARN calls to `std::str::from_utf8`
std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
//~^ WARN calls to `std::str::from_utf8`
}
}
fn main() {}

View file

@ -0,0 +1,110 @@
warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:19:9
|
LL | std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
|
note: the lint level is defined here
--> $DIR/invalid_from_utf8.rs:4:9
|
LL | #![warn(invalid_from_utf8_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:21:9
|
LL | std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:39:9
|
LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:41:9
|
LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:43:9
|
LL | std::str::from_utf8_unchecked(b"cl\x82ippy");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
--> $DIR/invalid_from_utf8.rs:45:9
|
LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:62:9
|
LL | std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
| ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
|
note: the lint level is defined here
--> $DIR/invalid_from_utf8.rs:5:9
|
LL | #![warn(invalid_from_utf8)]
| ^^^^^^^^^^^^^^^^^
warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:64:9
|
LL | std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
| ^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:82:9
|
LL | std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
| ^^^^^^^^^^^^^^^^^^^^-----------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:84:9
|
LL | std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
| ^^^^^^^^^^^^^^^^^^^^----------------------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:86:9
|
LL | std::str::from_utf8(b"cl\x82ippy");
| ^^^^^^^^^^^^^^^^^^^^-------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: calls to `std::str::from_utf8` with a invalid literal always return an error
--> $DIR/invalid_from_utf8.rs:88:9
|
LL | std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
| ^^^^^^^^^^^^^^^^^^^^---------------------------------^
| |
| the literal was valid UTF-8 up to the 2 bytes
warning: 12 warnings emitted

View file

@ -11,6 +11,8 @@
#![feature(never_type)] #![feature(never_type)]
#![feature(panic_always_abort)] #![feature(panic_always_abort)]
#![allow(invalid_from_utf8)]
extern crate libc; extern crate libc;
use std::alloc::{GlobalAlloc, Layout}; use std::alloc::{GlobalAlloc, Layout};

View file

@ -0,0 +1,11 @@
trait Cat {
fn nya() {}
}
fn uwu<T: Cat>(c: T) {
c.nya();
//~^ ERROR no method named `nya` found for type parameter `T` in the current scope
//~| Suggestion T::nya()
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0599]: no method named `nya` found for type parameter `T` in the current scope
--> $DIR/issue-103646.rs:6:7
|
LL | fn uwu<T: Cat>(c: T) {
| - method `nya` not found for this type parameter
LL | c.nya();
| --^^^--
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: `T::nya()`
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in the trait `Cat`
--> $DIR/issue-103646.rs:2:5
|
LL | fn nya() {}
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View file

@ -0,0 +1,13 @@
struct Client;
impl Client {
fn post<T: std::ops::Add>(&self, _: T, _: T) {}
}
fn f() {
let c = Client;
post(c, ());
//~^ ERROR cannot find function `post` in this scope
}
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0425]: cannot find function `post` in this scope
--> $DIR/issue-106929.rs:9:5
|
LL | post(c, ());
| ^^^^ not found in this scope
|
help: use the `.` operator to call the method `post` on `&Client`
|
LL - post(c, ());
LL + c.post(());
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.