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:
commit
a9251b6ce1
82 changed files with 798 additions and 436 deletions
|
@ -361,7 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::new(value),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
|||
let callee = cx.tcx.subst_and_normalize_erasing_regions(
|
||||
instance.substs,
|
||||
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());
|
||||
cx.dbg_scope_fn(callee, callee_fn_abi, None)
|
||||
|
|
|
@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.cx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::new(value),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
.try_subst_mir_and_normalize_erasing_regions(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
ty::EarlyBinder::new(value),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
.map_err(|_| err_inval!(TooGeneric))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
// `Predicate::subst_supertrait`, and it's no coincidence why.
|
||||
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);
|
||||
ty::Binder::bind_with_vars(subst_output, bound_vars)
|
||||
|
|
|
@ -796,14 +796,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
})
|
||||
});
|
||||
debug!(%ty);
|
||||
collected_tys.insert(def_id, ty::EarlyBinder::new(ty));
|
||||
collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
Err(err) => {
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
return_span,
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
// 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.
|
||||
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)
|
||||
.with_constness(tcx.constness(drop_impl_def_id));
|
||||
|
||||
|
|
|
@ -1407,7 +1407,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
}
|
||||
let mut param_count = CountParams::default();
|
||||
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)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
ty::EarlyBinder::new(output)
|
||||
ty::EarlyBinder::bind(output)
|
||||
}
|
||||
|
||||
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),
|
||||
)
|
||||
})
|
||||
.map(ty::EarlyBinder::new)
|
||||
.map(ty::EarlyBinder::bind)
|
||||
}
|
||||
|
||||
fn check_impl_constness(
|
||||
|
|
|
@ -86,7 +86,7 @@ pub(super) fn explicit_item_bounds(
|
|||
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
|
||||
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
|
||||
let opaque_ty = item.expect_opaque_ty();
|
||||
return ty::EarlyBinder::new(opaque_type_bounds(
|
||||
return ty::EarlyBinder::bind(opaque_type_bounds(
|
||||
tcx,
|
||||
opaque_def_id.expect_local(),
|
||||
opaque_ty.bounds,
|
||||
|
@ -124,7 +124,7 @@ pub(super) fn explicit_item_bounds(
|
|||
}
|
||||
_ => bug!("item_bounds called on {:?}", def_id),
|
||||
};
|
||||
ty::EarlyBinder::new(bounds)
|
||||
ty::EarlyBinder::bind(bounds)
|
||||
}
|
||||
|
||||
pub(super) fn item_bounds(
|
||||
|
|
|
@ -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()];
|
||||
}
|
||||
Err(_) => {
|
||||
return ty::EarlyBinder::new(tcx.ty_error_with_message(
|
||||
return ty::EarlyBinder::bind(tcx.ty_error_with_message(
|
||||
DUMMY_SP,
|
||||
"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);
|
||||
}
|
||||
};
|
||||
ty::EarlyBinder::new(output)
|
||||
ty::EarlyBinder::bind(output)
|
||||
}
|
||||
|
||||
fn infer_placeholder_type<'a>(
|
||||
|
|
|
@ -68,7 +68,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::EarlyBinder::new(required_predicates)
|
||||
ty::EarlyBinder::bind(required_predicates)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ pub(super) fn infer_predicates(
|
|||
if item_required_predicates.len() > item_predicates_len {
|
||||
predicates_added = true;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
|
||||
{
|
||||
// Try suggesting `foo(a)` -> `a.foo()` if possible.
|
||||
if let Some(ty) =
|
||||
self.suggest_call_as_method(
|
||||
&mut diag,
|
||||
segment,
|
||||
arg_exprs,
|
||||
call_expr,
|
||||
expected
|
||||
)
|
||||
{
|
||||
);
|
||||
diag.emit();
|
||||
return ty;
|
||||
} else {
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
|
||||
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>],
|
||||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
) {
|
||||
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
|
||||
// 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,
|
||||
expected.only_has_type(self),
|
||||
) else {
|
||||
return None;
|
||||
return;
|
||||
};
|
||||
|
||||
let pick = self.confirm_method(
|
||||
|
@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
segment,
|
||||
);
|
||||
if pick.illegal_sized_bound.is_some() {
|
||||
return None;
|
||||
return;
|
||||
}
|
||||
|
||||
let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
|
||||
|
@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
sugg,
|
||||
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(
|
||||
|
|
|
@ -473,6 +473,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut custom_span_label = false;
|
||||
|
||||
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() {
|
||||
err.note(
|
||||
"found the following associated functions; to be used as methods, \
|
||||
|
|
|
@ -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_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
|
||||
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||
|
||||
|
|
118
compiler/rustc_lint/src/invalid_from_utf8.rs
Normal file
118
compiler/rustc_lint/src/invalid_from_utf8.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@ mod expect;
|
|||
mod for_loops_over_fallibles;
|
||||
pub mod hidden_unicode_codepoints;
|
||||
mod internal;
|
||||
mod invalid_from_utf8;
|
||||
mod late;
|
||||
mod let_underscore;
|
||||
mod levels;
|
||||
|
@ -102,6 +103,7 @@ use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
|
|||
use for_loops_over_fallibles::*;
|
||||
use hidden_unicode_codepoints::*;
|
||||
use internal::*;
|
||||
use invalid_from_utf8::*;
|
||||
use let_underscore::*;
|
||||
use map_unit_fn::*;
|
||||
use methods::*;
|
||||
|
@ -207,6 +209,7 @@ late_lint_methods!(
|
|||
HardwiredLints: HardwiredLints,
|
||||
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
|
||||
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
|
||||
InvalidFromUtf8: InvalidFromUtf8,
|
||||
VariantSizeDifferences: VariantSizeDifferences,
|
||||
BoxPointers: BoxPointers,
|
||||
PathStatements: PathStatements,
|
||||
|
|
|
@ -699,6 +699,25 @@ pub struct ForgetCopyDiag<'a> {
|
|||
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
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_hidden_unicode_codepoints)]
|
||||
|
|
|
@ -858,7 +858,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
} else {
|
||||
tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
|
||||
};
|
||||
ty::EarlyBinder::new(&*output)
|
||||
ty::EarlyBinder::bind(&*output)
|
||||
}
|
||||
|
||||
fn get_variant(
|
||||
|
|
|
@ -1730,7 +1730,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
ty::Closure(_, substs) => {
|
||||
let constness = self.tcx.constness(def_id.to_def_id());
|
||||
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"),
|
||||
|
|
|
@ -476,7 +476,7 @@ impl<'tcx> Body<'tcx> {
|
|||
/// Returns the return type; it always return first element from `local_decls` array.
|
||||
#[inline]
|
||||
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.
|
||||
|
|
|
@ -573,7 +573,7 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
/// Due to normalization being eager, this applies even if
|
||||
/// the associated type is behind a pointer (e.g., issue #31299).
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
),
|
||||
};
|
||||
ty::EarlyBinder::new(Const::from_anon_const(tcx, default_def_id))
|
||||
ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ impl<'tcx> GenericPredicates<'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
) -> 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))]
|
||||
|
@ -358,7 +358,7 @@ impl<'tcx> GenericPredicates<'tcx> {
|
|||
}
|
||||
instantiated
|
||||
.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));
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
|
|||
fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
|
||||
match self {
|
||||
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) {
|
||||
Some(0) => Self::True,
|
||||
Some(1..) => Self::False,
|
||||
|
@ -167,7 +167,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
|
|||
Some(pred)
|
||||
}
|
||||
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) {
|
||||
None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
|
||||
|
|
|
@ -764,7 +764,7 @@ impl<'tcx> Predicate<'tcx> {
|
|||
let shifted_pred =
|
||||
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>
|
||||
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]
|
||||
let bound_vars =
|
||||
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
|
||||
|
|
|
@ -568,7 +568,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
|||
let layout = tcx.generator_layout(def_id).unwrap();
|
||||
layout.variant_fields.iter().map(move |variant| {
|
||||
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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<T> EarlyBinder<T> {
|
||||
pub fn new(inner: T) -> EarlyBinder<T> {
|
||||
pub fn bind(inner: T) -> EarlyBinder<T> {
|
||||
EarlyBinder(inner)
|
||||
}
|
||||
|
||||
|
|
|
@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
.as_ref()
|
||||
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
|
||||
.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
|
||||
|
|
|
@ -96,13 +96,13 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
|
|||
|
||||
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> {
|
||||
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<'_>>> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||
// If the inner type matches the type bound by `Pointer`
|
||||
if inner_ty == bound_ty {
|
||||
// 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)) =
|
||||
FunctionItemRefChecker::is_fn_ref(subst_ty)
|
||||
{
|
||||
|
|
|
@ -192,7 +192,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
ty::EarlyBinder::new(callee_body.clone()),
|
||||
ty::EarlyBinder::bind(callee_body.clone()),
|
||||
) else {
|
||||
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.
|
||||
let ty = callsite
|
||||
.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 {
|
||||
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.
|
||||
let ty = self
|
||||
.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) {
|
||||
self.cost += CALL_PENALTY;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
|
@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
// Don't give intrinsics the extra penalty for calls
|
||||
INSTR_COST
|
||||
|
|
|
@ -47,7 +47,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(
|
||||
tcx,
|
||||
param_env,
|
||||
ty::EarlyBinder::new(substs),
|
||||
ty::EarlyBinder::bind(substs),
|
||||
) else {
|
||||
trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping");
|
||||
continue;
|
||||
|
|
|
@ -69,7 +69,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
|||
// of this function. Is this intentional?
|
||||
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 = EarlyBinder::new(body.clone()).subst(tcx, substs);
|
||||
let body = EarlyBinder::bind(body.clone()).subst(tcx, substs);
|
||||
debug!("make_shim({:?}) = {:?}", instance, body);
|
||||
return body;
|
||||
}
|
||||
|
|
|
@ -677,7 +677,7 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
|
|||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::new(value),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
closure_instance.substs,
|
||||
param_env,
|
||||
ty::EarlyBinder::new(before_feature_tys),
|
||||
ty::EarlyBinder::bind(before_feature_tys),
|
||||
);
|
||||
let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
|
||||
closure_instance.substs,
|
||||
param_env,
|
||||
ty::EarlyBinder::new(after_feature_tys),
|
||||
ty::EarlyBinder::bind(after_feature_tys),
|
||||
);
|
||||
|
||||
let new_size = tcx
|
||||
|
|
|
@ -1454,6 +1454,10 @@ symbols! {
|
|||
stop_after_dataflow,
|
||||
store,
|
||||
str,
|
||||
str_from_utf8,
|
||||
str_from_utf8_mut,
|
||||
str_from_utf8_unchecked,
|
||||
str_from_utf8_unchecked_mut,
|
||||
str_split_whitespace,
|
||||
str_trim,
|
||||
str_trim_end,
|
||||
|
|
|
@ -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);
|
||||
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 {
|
||||
|
|
|
@ -487,7 +487,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
|
|||
tcx,
|
||||
ObligationCause::dummy_with_span(*span),
|
||||
param_env,
|
||||
ty::EarlyBinder::new(*pred).subst(tcx, impl_trait_ref.substs),
|
||||
ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
|
||||
)
|
||||
})
|
||||
});
|
||||
|
|
|
@ -642,7 +642,7 @@ fn receiver_for_self_ty<'tcx>(
|
|||
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!(
|
||||
"receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
|
||||
receiver_ty, self_ty, method_def_id, result
|
||||
|
|
|
@ -307,13 +307,13 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
|||
// there, but that needs some way to handle cycles.
|
||||
constraints
|
||||
.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
|
||||
.outlives
|
||||
.extend(outlives.iter().map(|t| EarlyBinder::new(*t).subst(tcx, substs)));
|
||||
.extend(outlives.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
|
||||
constraints
|
||||
.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
|
||||
|
|
|
@ -301,7 +301,7 @@ fn associated_type_for_impl_trait_in_trait(
|
|||
trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
|
||||
|
||||
// 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(),
|
||||
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
|
||||
)));
|
||||
|
|
|
@ -419,7 +419,7 @@ pub fn thir_abstract_const(
|
|||
|
||||
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) {
|
||||
|
|
|
@ -610,7 +610,7 @@ fn generator_layout<'tcx>(
|
|||
) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
|
||||
use SavedLocalEligibility::*;
|
||||
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 {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
|
|
|
@ -210,7 +210,7 @@ fn drop_tys_helper<'tcx>(
|
|||
match subty.kind() {
|
||||
ty::Adt(adt_id, subst) => {
|
||||
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),
|
||||
|
|
|
@ -507,7 +507,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
|
|||
|
||||
if self_ty_matches {
|
||||
debug!("issue33140_self_ty - MATCHES!");
|
||||
Some(EarlyBinder::new(self_ty))
|
||||
Some(EarlyBinder::bind(self_ty))
|
||||
} else {
|
||||
debug!("issue33140_self_ty - non-matching self type");
|
||||
None
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![cfg_attr(not(bootstrap), allow(invalid_from_utf8))]
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||
|
|
|
@ -94,8 +94,9 @@ impl fmt::Display for AllocError {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
|
||||
/// until the instance and all of its copies and clones are dropped,
|
||||
/// * Memory blocks returned from an allocator that are [*currently allocated*] must point to
|
||||
/// 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
|
||||
/// allocator. A copied or cloned allocator must behave like the same allocator, and
|
||||
|
|
|
@ -84,6 +84,7 @@ use super::Utf8Error;
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
|
||||
#[rustc_allow_const_fn_unstable(str_internals)]
|
||||
#[rustc_diagnostic_item = "str_from_utf8"]
|
||||
pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
|
||||
// FIXME: This should use `?` again, once it's `const`
|
||||
match run_utf8_validation(v) {
|
||||
|
@ -127,6 +128,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
|
|||
/// errors that can be returned.
|
||||
#[stable(feature = "str_mut_extras", since = "1.20.0")]
|
||||
#[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> {
|
||||
// This should use `?` again, once it's `const`
|
||||
match run_utf8_validation(v) {
|
||||
|
@ -167,6 +169,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
|
|||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.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 {
|
||||
// SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
|
||||
// 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]
|
||||
#[stable(feature = "str_mut_extras", since = "1.20.0")]
|
||||
#[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 {
|
||||
// SAFETY: the caller must guarantee that the bytes `v`
|
||||
// are valid UTF-8, thus the cast to `*mut str` is safe.
|
||||
|
|
|
@ -103,11 +103,14 @@ impl RunConfig<'_> {
|
|||
}
|
||||
|
||||
/// Return a list of crate names selected by `run.paths`.
|
||||
#[track_caller]
|
||||
pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
|
||||
let mut crates = Vec::new();
|
||||
for krate in &self.paths {
|
||||
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());
|
||||
}
|
||||
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
|
||||
/// 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.
|
||||
///
|
||||
/// `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 {
|
||||
for krate in crates {
|
||||
let path = krate.local_path(self.builder);
|
||||
|
@ -487,7 +473,15 @@ impl<'a> ShouldRun<'a> {
|
|||
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 {
|
||||
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 {
|
||||
Kind::Test => "Testing",
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::*;
|
||||
use crate::config::{Config, DryRun, TargetSelection};
|
||||
use crate::doc::DocumentationFormat;
|
||||
use std::thread;
|
||||
|
||||
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 {
|
||||
($host:ident => $target:ident, stage = $stage:literal) => {
|
||||
compile::Rustc::new(
|
||||
|
@ -144,6 +155,9 @@ fn alias_and_path_for_library() {
|
|||
first(cache.all::<compile::Std>()),
|
||||
&[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]
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
//! 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::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::tool::{prepare_tool_cargo, SourceType};
|
||||
use crate::INTERNER;
|
||||
|
@ -12,6 +14,12 @@ use std::path::{Path, PathBuf};
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Std {
|
||||
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)
|
||||
|
@ -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 {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.all_krates("sysroot").path("library")
|
||||
run.crate_or_deps("sysroot").path("library")
|
||||
}
|
||||
|
||||
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<'_>) {
|
||||
|
@ -97,7 +112,14 @@ impl Step for Std {
|
|||
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(
|
||||
builder,
|
||||
cargo,
|
||||
|
@ -117,7 +139,8 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -147,8 +170,8 @@ impl Step for Std {
|
|||
// Explicitly pass -p for all dependencies krates -- this will force cargo
|
||||
// to also check the tests/benches/examples for these crates, rather
|
||||
// than just the leaf crate.
|
||||
for krate in builder.in_tree_crates("test", Some(target)) {
|
||||
cargo.arg("-p").arg(krate.name);
|
||||
for krate in &*self.crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
|
||||
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)]
|
||||
pub struct Rustc {
|
||||
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 {
|
||||
|
@ -175,11 +214,12 @@ impl Step for Rustc {
|
|||
const DEFAULT: bool = true;
|
||||
|
||||
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<'_>) {
|
||||
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.
|
||||
|
@ -200,7 +240,7 @@ impl Step for Rustc {
|
|||
builder.ensure(crate::compile::Std::new(compiler, compiler.host));
|
||||
builder.ensure(crate::compile::Std::new(compiler, target));
|
||||
} else {
|
||||
builder.ensure(Std { target });
|
||||
builder.ensure(Std::new(target));
|
||||
}
|
||||
|
||||
let mut cargo = builder.cargo(
|
||||
|
@ -218,14 +258,17 @@ impl Step for Rustc {
|
|||
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
|
||||
// than just the leaf crate.
|
||||
for krate in builder.in_tree_crates("rustc-main", Some(target)) {
|
||||
cargo.arg("-p").arg(krate.name);
|
||||
for krate in &*self.crates {
|
||||
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(
|
||||
builder,
|
||||
cargo,
|
||||
|
@ -268,7 +311,7 @@ impl Step for CodegenBackend {
|
|||
let target = self.target;
|
||||
let backend = self.backend;
|
||||
|
||||
builder.ensure(Rustc { target });
|
||||
builder.ensure(Rustc::new(target, builder));
|
||||
|
||||
let mut cargo = builder.cargo(
|
||||
compiler,
|
||||
|
@ -318,7 +361,7 @@ impl Step for RustAnalyzer {
|
|||
let compiler = builder.compiler(builder.top_stage, builder.config.build);
|
||||
let target = self.target;
|
||||
|
||||
builder.ensure(Std { target });
|
||||
builder.ensure(Std::new(target));
|
||||
|
||||
let mut cargo = prepare_tool_cargo(
|
||||
builder,
|
||||
|
@ -386,7 +429,7 @@ macro_rules! tool_check_step {
|
|||
let compiler = builder.compiler(builder.top_stage, builder.config.build);
|
||||
let target = self.target;
|
||||
|
||||
builder.ensure(Rustc { target });
|
||||
builder.ensure(Rustc::new(target, builder));
|
||||
|
||||
let mut cargo = prepare_tool_cargo(
|
||||
builder,
|
||||
|
|
|
@ -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 {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
|
@ -62,16 +73,10 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
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 {
|
||||
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
|
||||
target: run.target,
|
||||
crates,
|
||||
crates: make_run_crates(&run, "library"),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -615,6 +620,8 @@ impl Step for Rustc {
|
|||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let mut crates = run.builder.in_tree_crates("rustc-main", None);
|
||||
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" {
|
||||
crates.swap_remove(i);
|
||||
break;
|
||||
|
|
|
@ -106,11 +106,7 @@ impl Step for JsonDocs {
|
|||
/// Builds the `rust-docs-json` installer component.
|
||||
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
|
||||
let host = self.host;
|
||||
builder.ensure(crate::doc::Std {
|
||||
stage: builder.top_stage,
|
||||
target: host,
|
||||
format: DocumentationFormat::JSON,
|
||||
});
|
||||
builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON));
|
||||
|
||||
let dest = "share/doc/rust/json";
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//! Everything here is basically just a shim around calling either `rustbook` or
|
||||
//! `rustdoc`.
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
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::cache::{Interned, INTERNER};
|
||||
use crate::compile;
|
||||
use crate::compile::make_run_crates;
|
||||
use crate::config::{Config, TargetSelection};
|
||||
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
|
||||
use crate::util::{symlink_dir, t, up_to_date};
|
||||
|
@ -87,15 +87,6 @@ book!(
|
|||
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)]
|
||||
pub struct UnstableBook {
|
||||
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 stage: u32,
|
||||
pub target: TargetSelection,
|
||||
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 {
|
||||
|
@ -438,7 +436,7 @@ impl Step for Std {
|
|||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
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<'_>) {
|
||||
|
@ -450,6 +448,7 @@ impl Step for Std {
|
|||
} else {
|
||||
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
|
||||
/// 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 target = self.target;
|
||||
let out = match self.format {
|
||||
|
@ -471,41 +470,24 @@ impl Step for Std {
|
|||
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 {
|
||||
DocumentationFormat::HTML => vec![
|
||||
OsStr::new("--markdown-css"),
|
||||
OsStr::new("rust.css"),
|
||||
OsStr::new("--markdown-no-toc"),
|
||||
OsStr::new("--index-page"),
|
||||
&index_page,
|
||||
],
|
||||
DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")],
|
||||
DocumentationFormat::HTML => {
|
||||
vec!["--markdown-css", "rust.css", "--markdown-no-toc", "--index-page", &index_page]
|
||||
}
|
||||
DocumentationFormat::JSON => vec!["--output-format", "json"],
|
||||
};
|
||||
|
||||
if !builder.config.docs_minification {
|
||||
extra_args.push(OsStr::new("--disable-minification"));
|
||||
extra_args.push("--disable-minification");
|
||||
}
|
||||
|
||||
let requested_crates = builder
|
||||
.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);
|
||||
doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
|
||||
|
||||
// Don't open if the format is json
|
||||
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
|
||||
// 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" {
|
||||
// For `x.py doc library --open`, open `std` by default.
|
||||
let index = out.join("std").join("index.html");
|
||||
|
@ -538,7 +524,7 @@ impl Step for Std {
|
|||
/// or remote link.
|
||||
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 {
|
||||
HTML,
|
||||
JSON,
|
||||
|
@ -563,24 +549,22 @@ fn doc_std(
|
|||
stage: u32,
|
||||
target: TargetSelection,
|
||||
out: &Path,
|
||||
extra_args: &[&OsStr],
|
||||
extra_args: &[&str],
|
||||
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) {
|
||||
panic!(
|
||||
"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 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_dir =
|
||||
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.
|
||||
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, "rustdoc");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "doc");
|
||||
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
|
||||
cargo
|
||||
.arg("--no-deps")
|
||||
.arg("--target-dir")
|
||||
.arg(&*target_dir.to_string_lossy())
|
||||
.arg("-p")
|
||||
.arg(package)
|
||||
.arg("-Zskip-rustdoc-fingerprint")
|
||||
.arg("--")
|
||||
.arg("-Z")
|
||||
.arg("unstable-options")
|
||||
.arg("--resource-suffix")
|
||||
.arg(&builder.version)
|
||||
.args(extra_args);
|
||||
if builder.config.library_docs_private_items {
|
||||
cargo.arg("--document-private-items").arg("--document-hidden-items");
|
||||
.rustdocflag("-Z")
|
||||
.rustdocflag("unstable-options")
|
||||
.rustdocflag("--resource-suffix")
|
||||
.rustdocflag(&builder.version);
|
||||
for arg in extra_args {
|
||||
cargo.rustdocflag(arg);
|
||||
}
|
||||
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 {
|
||||
run_cargo_rustdoc_for(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;
|
||||
}
|
||||
for krate in built_crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
|
||||
builder.run(&mut cargo.into());
|
||||
builder.cp_r(&out_dir, &out);
|
||||
}
|
||||
|
||||
|
@ -626,6 +617,28 @@ fn doc_std(
|
|||
pub struct Rustc {
|
||||
pub stage: u32,
|
||||
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 {
|
||||
|
@ -641,7 +654,11 @@ impl Step for Rustc {
|
|||
}
|
||||
|
||||
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.
|
||||
|
@ -654,15 +671,6 @@ impl Step for Rustc {
|
|||
let stage = self.stage;
|
||||
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.
|
||||
let out = builder.compiler_doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
|
@ -672,7 +680,13 @@ impl Step for Rustc {
|
|||
let compiler = builder.compiler(stage, 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
|
||||
// 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("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;
|
||||
for krate in compiler_crates {
|
||||
for krate in &*self.crates {
|
||||
// Create all crate output directories first to make sure rustdoc uses
|
||||
// relative links.
|
||||
// FIXME: Cargo should probably do this itself.
|
||||
|
@ -785,7 +785,7 @@ macro_rules! tool_doc {
|
|||
|
||||
if true $(&& $rustc_tool)? {
|
||||
// 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.
|
||||
// FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
|
||||
|
|
|
@ -1020,8 +1020,8 @@ impl Build {
|
|||
host: impl Into<Option<TargetSelection>>,
|
||||
target: impl Into<Option<TargetSelection>>,
|
||||
) -> Option<gha::Group> {
|
||||
let action = action.into();
|
||||
let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}");
|
||||
let action = action.into().description();
|
||||
let msg = |fmt| format!("{action} stage{stage} {what}{fmt}");
|
||||
let msg = if let Some(target) = target.into() {
|
||||
let host = host.into().unwrap();
|
||||
if host == target {
|
||||
|
|
|
@ -101,7 +101,7 @@ impl Step for CrateBootstrap {
|
|||
);
|
||||
builder.info(&format!(
|
||||
"{} {} stage0 ({})",
|
||||
builder.kind.test_description(),
|
||||
builder.kind.description(),
|
||||
path,
|
||||
bootstrap_host,
|
||||
));
|
||||
|
@ -220,7 +220,7 @@ impl Step for HtmlCheck {
|
|||
}
|
||||
// Ensure that a few different kinds of documentation are available.
|
||||
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)));
|
||||
}
|
||||
|
@ -886,11 +886,11 @@ impl Step for RustdocJSStd {
|
|||
command.arg("--test-file").arg(path);
|
||||
}
|
||||
}
|
||||
builder.ensure(crate::doc::Std {
|
||||
target: self.target,
|
||||
stage: builder.top_stage,
|
||||
format: DocumentationFormat::HTML,
|
||||
});
|
||||
builder.ensure(crate::doc::Std::new(
|
||||
builder.top_stage,
|
||||
self.target,
|
||||
DocumentationFormat::HTML,
|
||||
));
|
||||
builder.run(&mut command);
|
||||
} else {
|
||||
builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests");
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.16.4
|
||||
0.16.5
|
|
@ -40,7 +40,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
|
|||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
|
||||
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_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
|
||||
|
|
|
@ -212,7 +212,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
|
||||
crate::int_plus_one::INT_PLUS_ONE_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_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
|
||||
crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
|
||||
|
|
|
@ -1219,7 +1219,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
|
|||
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 infcx = cx.tcx.infer_ctxt().build();
|
||||
infcx.predicate_must_hold_modulo_regions(&obligation)
|
||||
|
|
|
@ -243,7 +243,7 @@ fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, substs
|
|||
| ty::Ref(..)
|
||||
| ty::Slice(_)
|
||||
| ty::Tuple(_) => {
|
||||
format!("<{}>", EarlyBinder::new(ty).subst(cx.tcx, substs))
|
||||
format!("<{}>", EarlyBinder::bind(ty).subst(cx.tcx, substs))
|
||||
},
|
||||
_ => ty.to_string(),
|
||||
}
|
||||
|
|
|
@ -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`",
|
||||
);
|
||||
}
|
|
@ -157,7 +157,6 @@ mod inline_fn_without_body;
|
|||
mod instant_subtraction;
|
||||
mod int_plus_one;
|
||||
mod invalid_upcast_comparisons;
|
||||
mod invalid_utf8_in_unchecked;
|
||||
mod items_after_statements;
|
||||
mod items_after_test_module;
|
||||
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())));
|
||||
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(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
|
||||
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(|_| Box::new(partialeq_to_none::PartialeqToNone));
|
||||
|
|
|
@ -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 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 {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
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);
|
||||
!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();
|
||||
if output_ty.contains(*param_ty) {
|
||||
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;
|
||||
ty = new_ty;
|
||||
continue;
|
||||
|
|
|
@ -43,6 +43,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
|||
("clippy::into_iter_on_array", "array_into_iter"),
|
||||
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
|
||||
("clippy::invalid_ref", "invalid_value"),
|
||||
("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"),
|
||||
("clippy::let_underscore_drop", "let_underscore_drop"),
|
||||
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
|
||||
("clippy::panic_params", "non_fmt_panics"),
|
||||
|
|
|
@ -462,7 +462,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
let substs = if self.substs.is_empty() {
|
||||
substs
|
||||
} else {
|
||||
EarlyBinder::new(substs).subst(self.lcx.tcx, self.substs)
|
||||
EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs)
|
||||
};
|
||||
|
||||
let result = self
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
#![allow(invalid_from_utf8_unchecked)]
|
||||
#![allow(let_underscore_drop)]
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
|
@ -87,6 +88,7 @@
|
|||
#![warn(array_into_iter)]
|
||||
#![warn(invalid_atomic_ordering)]
|
||||
#![warn(invalid_value)]
|
||||
#![warn(invalid_from_utf8_unchecked)]
|
||||
#![warn(let_underscore_drop)]
|
||||
#![warn(enum_intrinsics_non_enums)]
|
||||
#![warn(non_fmt_panics)]
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
#![allow(invalid_from_utf8_unchecked)]
|
||||
#![allow(let_underscore_drop)]
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
|
@ -87,6 +88,7 @@
|
|||
#![warn(clippy::into_iter_on_array)]
|
||||
#![warn(clippy::invalid_atomic_ordering)]
|
||||
#![warn(clippy::invalid_ref)]
|
||||
#![warn(clippy::invalid_utf8_in_unchecked)]
|
||||
#![warn(clippy::let_underscore_drop)]
|
||||
#![warn(clippy::mem_discriminant_non_enum)]
|
||||
#![warn(clippy::panic_params)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:51:9
|
||||
--> $DIR/rename.rs:52:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:53:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:56:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:65:9
|
||||
|
|
||||
LL | #![warn(clippy::new_without_default_derive)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:66:9
|
||||
|
|
||||
LL | #![warn(clippy::option_and_then_some)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:68:9
|
||||
--> $DIR/rename.rs:69:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ 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`
|
||||
--> $DIR/rename.rs:90:9
|
||||
--> $DIR/rename.rs:92:9
|
||||
|
|
||||
LL | #![warn(clippy::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`
|
||||
--> $DIR/rename.rs:91:9
|
||||
--> $DIR/rename.rs:93:9
|
||||
|
|
||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
||||
error: aborting due to 48 previous errors
|
||||
error: aborting due to 49 previous errors
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ call-function: ("check-style", {
|
|||
})
|
||||
call-function: ("check-style", {
|
||||
"theme": "dark",
|
||||
"background": "rgb(73, 74, 61)",
|
||||
"border": "rgb(187, 116, 16)",
|
||||
"background": "#494a3d",
|
||||
"border": "#bb7410",
|
||||
})
|
||||
call-function: ("check-style", {
|
||||
"theme": "light",
|
||||
"background": "rgb(253, 255, 211)",
|
||||
"border": "rgb(173, 124, 55)",
|
||||
"background": "#fdffd3",
|
||||
"border": "#ad7c37",
|
||||
})
|
||||
|
|
93
tests/ui/lint/invalid_from_utf8.rs
Normal file
93
tests/ui/lint/invalid_from_utf8.rs
Normal 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() {}
|
110
tests/ui/lint/invalid_from_utf8.stderr
Normal file
110
tests/ui/lint/invalid_from_utf8.stderr
Normal 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
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
#![feature(never_type)]
|
||||
#![feature(panic_always_abort)]
|
||||
|
||||
#![allow(invalid_from_utf8)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use std::alloc::{GlobalAlloc, Layout};
|
||||
|
|
11
tests/ui/suggestions/issue-103646.rs
Normal file
11
tests/ui/suggestions/issue-103646.rs
Normal 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() {}
|
21
tests/ui/suggestions/issue-103646.stderr
Normal file
21
tests/ui/suggestions/issue-103646.stderr
Normal 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`.
|
13
tests/ui/typeck/issue-106929.rs
Normal file
13
tests/ui/typeck/issue-106929.rs
Normal 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() {}
|
15
tests/ui/typeck/issue-106929.stderr
Normal file
15
tests/ui/typeck/issue-106929.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue