Skip to content

Commit a9251b6

Browse files
committed
Auto merge of rust-lang#112102 - Nilstrieb:rollup-ivu1hmc, r=Nilstrieb
Rollup of 7 pull requests Successful merges: - rust-lang#107916 (fix comment on Allocator trait) - rust-lang#111543 (Uplift `clippy::invalid_utf8_in_unchecked` lint) - rust-lang#111872 (fix: dedup `static_candidates` before report) - rust-lang#111955 (bootstrap: Various Step refactors) - rust-lang#112060 (`EarlyBinder::new` -> `EarlyBinder::bind`) - rust-lang#112064 (Migrate GUI colors test to original CSS color format) - rust-lang#112100 (Don't typecheck recovered method call from suggestion) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3266c36 + cc12182 commit a9251b6

File tree

82 files changed

+796
-434
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+796
-434
lines changed

compiler/rustc_codegen_cranelift/src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
361361
self.instance.subst_mir_and_normalize_erasing_regions(
362362
self.tcx,
363363
ty::ParamEnv::reveal_all(),
364-
ty::EarlyBinder::new(value),
364+
ty::EarlyBinder::bind(value),
365365
)
366366
}
367367

compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn make_mir_scope<'ll, 'tcx>(
9393
let callee = cx.tcx.subst_and_normalize_erasing_regions(
9494
instance.substs,
9595
ty::ParamEnv::reveal_all(),
96-
ty::EarlyBinder::new(callee),
96+
ty::EarlyBinder::bind(callee),
9797
);
9898
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
9999
cx.dbg_scope_fn(callee, callee_fn_abi, None)

compiler/rustc_codegen_ssa/src/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
111111
self.instance.subst_mir_and_normalize_erasing_regions(
112112
self.cx.tcx(),
113113
ty::ParamEnv::reveal_all(),
114-
ty::EarlyBinder::new(value),
114+
ty::EarlyBinder::bind(value),
115115
)
116116
}
117117
}

compiler/rustc_const_eval/src/interpret/eval_context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
497497
.try_subst_mir_and_normalize_erasing_regions(
498498
*self.tcx,
499499
self.param_env,
500-
ty::EarlyBinder::new(value),
500+
ty::EarlyBinder::bind(value),
501501
)
502502
.map_err(|_| err_inval!(TooGeneric))
503503
}

compiler/rustc_hir_analysis/src/astconv/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12801280
// params (and trait ref's late bound params). This logic is very similar to
12811281
// `Predicate::subst_supertrait`, and it's no coincidence why.
12821282
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
1283-
let subst_output = ty::EarlyBinder::new(shifted_output).subst(tcx, substs);
1283+
let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs);
12841284

12851285
let bound_vars = tcx.late_bound_vars(binding.hir_id);
12861286
ty::Binder::bind_with_vars(subst_output, bound_vars)

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -796,14 +796,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
796796
})
797797
});
798798
debug!(%ty);
799-
collected_tys.insert(def_id, ty::EarlyBinder::new(ty));
799+
collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
800800
}
801801
Err(err) => {
802802
let reported = tcx.sess.delay_span_bug(
803803
return_span,
804804
format!("could not fully resolve: {ty} => {err:?}"),
805805
);
806-
collected_tys.insert(def_id, ty::EarlyBinder::new(tcx.ty_error(reported)));
806+
collected_tys.insert(def_id, ty::EarlyBinder::bind(tcx.ty_error(reported)));
807807
}
808808
}
809809
}

compiler/rustc_hir_analysis/src/check/dropck.rs

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

compiler/rustc_hir_analysis/src/check/wfcheck.rs

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

compiler/rustc_hir_analysis/src/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
11241124
bug!("unexpected sort of node in fn_sig(): {:?}", x);
11251125
}
11261126
};
1127-
ty::EarlyBinder::new(output)
1127+
ty::EarlyBinder::bind(output)
11281128
}
11291129

11301130
fn infer_return_ty_for_fn_sig<'tcx>(
@@ -1312,7 +1312,7 @@ fn impl_trait_ref(
13121312
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
13131313
)
13141314
})
1315-
.map(ty::EarlyBinder::new)
1315+
.map(ty::EarlyBinder::bind)
13161316
}
13171317

13181318
fn check_impl_constness(

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(super) fn explicit_item_bounds(
8686
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
8787
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
8888
let opaque_ty = item.expect_opaque_ty();
89-
return ty::EarlyBinder::new(opaque_type_bounds(
89+
return ty::EarlyBinder::bind(opaque_type_bounds(
9090
tcx,
9191
opaque_def_id.expect_local(),
9292
opaque_ty.bounds,
@@ -124,7 +124,7 @@ pub(super) fn explicit_item_bounds(
124124
}
125125
_ => bug!("item_bounds called on {:?}", def_id),
126126
};
127-
ty::EarlyBinder::new(bounds)
127+
ty::EarlyBinder::bind(bounds)
128128
}
129129

130130
pub(super) fn item_bounds(

compiler/rustc_hir_analysis/src/collect/type_of.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
323323
return map[&assoc_item.trait_item_def_id.unwrap()];
324324
}
325325
Err(_) => {
326-
return ty::EarlyBinder::new(tcx.ty_error_with_message(
326+
return ty::EarlyBinder::bind(tcx.ty_error_with_message(
327327
DUMMY_SP,
328328
"Could not collect return position impl trait in trait tys",
329329
));
@@ -497,7 +497,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
497497
bug!("unexpected sort of node in type_of(): {:?}", x);
498498
}
499499
};
500-
ty::EarlyBinder::new(output)
500+
ty::EarlyBinder::bind(output)
501501
}
502502

503503
fn infer_placeholder_type<'a>(

compiler/rustc_hir_analysis/src/outlives/explicit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
6868
}
6969
}
7070

71-
ty::EarlyBinder::new(required_predicates)
71+
ty::EarlyBinder::bind(required_predicates)
7272
})
7373
}
7474
}

compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub(super) fn infer_predicates(
7474
if item_required_predicates.len() > item_predicates_len {
7575
predicates_added = true;
7676
global_inferred_outlives
77-
.insert(item_did.to_def_id(), ty::EarlyBinder::new(item_required_predicates));
77+
.insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates));
7878
}
7979
}
8080

compiler/rustc_hir_typeck/src/callee.rs

+14-32
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
420420
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
421421
{
422422
// Try suggesting `foo(a)` -> `a.foo()` if possible.
423-
if let Some(ty) =
424-
self.suggest_call_as_method(
425-
&mut diag,
426-
segment,
427-
arg_exprs,
428-
call_expr,
429-
expected
430-
)
431-
{
432-
diag.emit();
433-
return ty;
434-
} else {
435-
diag.emit();
436-
}
423+
self.suggest_call_as_method(
424+
&mut diag,
425+
segment,
426+
arg_exprs,
427+
call_expr,
428+
expected
429+
);
430+
diag.emit();
437431
}
438432

439433
let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
@@ -496,9 +490,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
496490
arg_exprs: &'tcx [hir::Expr<'tcx>],
497491
call_expr: &'tcx hir::Expr<'tcx>,
498492
expected: Expectation<'tcx>,
499-
) -> Option<Ty<'tcx>> {
493+
) {
500494
if let [callee_expr, rest @ ..] = arg_exprs {
501-
let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?;
495+
let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else {
496+
return;
497+
};
502498

503499
// First, do a probe with `IsSuggestion(true)` to avoid emitting
504500
// any strange errors. If it's successful, then we'll do a true
@@ -513,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
513509
ProbeScope::AllTraits,
514510
expected.only_has_type(self),
515511
) else {
516-
return None;
512+
return;
517513
};
518514

519515
let pick = self.confirm_method(
@@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
525521
segment,
526522
);
527523
if pick.illegal_sized_bound.is_some() {
528-
return None;
524+
return;
529525
}
530526

531527
let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
@@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
567563
sugg,
568564
Applicability::MaybeIncorrect,
569565
);
570-
571-
// Let's check the method fully now
572-
let return_ty = self.check_method_argument_types(
573-
segment.ident.span,
574-
call_expr,
575-
Ok(pick.callee),
576-
rest,
577-
TupleArgumentsFlag::DontTupleArguments,
578-
expected,
579-
);
580-
581-
return Some(return_ty);
582566
}
583567
}
584-
585-
None
586568
}
587569

588570
fn report_invalid_callee(

compiler/rustc_hir_typeck/src/method/suggest.rs

+6
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
473473
let mut custom_span_label = false;
474474

475475
let static_candidates = &mut no_match_data.static_candidates;
476+
477+
// `static_candidates` may have same candidates appended by
478+
// inherent and extension, which may result in incorrect
479+
// diagnostic.
480+
static_candidates.dedup();
481+
476482
if !static_candidates.is_empty() {
477483
err.note(
478484
"found the following associated functions; to be used as methods, \

compiler/rustc_lint/messages.ftl

+8
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
304304
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
305305
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
306306
307+
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
308+
lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
309+
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
310+
311+
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
312+
lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
313+
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
314+
307315
lint_lintpass_by_hand = implementing `LintPass` by hand
308316
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
309317
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use std::str::Utf8Error;
2+
3+
use rustc_ast::{BorrowKind, LitKind};
4+
use rustc_hir::{Expr, ExprKind};
5+
use rustc_span::source_map::Spanned;
6+
use rustc_span::sym;
7+
8+
use crate::lints::InvalidFromUtf8Diag;
9+
use crate::{LateContext, LateLintPass, LintContext};
10+
11+
declare_lint! {
12+
/// The `invalid_from_utf8_unchecked` lint checks for calls to
13+
/// `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`
14+
/// with an invalid UTF-8 literal.
15+
///
16+
/// ### Example
17+
///
18+
/// ```rust,compile_fail
19+
/// # #[allow(unused)]
20+
/// unsafe {
21+
/// std::str::from_utf8_unchecked(b"Ru\x82st");
22+
/// }
23+
/// ```
24+
///
25+
/// {{produces}}
26+
///
27+
/// ### Explanation
28+
///
29+
/// Creating such a `str` would result in undefined behavior as per documentation
30+
/// for `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`.
31+
pub INVALID_FROM_UTF8_UNCHECKED,
32+
Deny,
33+
"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"
34+
}
35+
36+
declare_lint! {
37+
/// The `invalid_from_utf8` lint checks for calls to
38+
/// `std::str::from_utf8` and `std::str::from_utf8_mut`
39+
/// with an invalid UTF-8 literal.
40+
///
41+
/// ### Example
42+
///
43+
/// ```rust
44+
/// # #[allow(unused)]
45+
/// std::str::from_utf8(b"Ru\x82st");
46+
/// ```
47+
///
48+
/// {{produces}}
49+
///
50+
/// ### Explanation
51+
///
52+
/// Trying to create such a `str` would always return an error as per documentation
53+
/// for `std::str::from_utf8` and `std::str::from_utf8_mut`.
54+
pub INVALID_FROM_UTF8,
55+
Warn,
56+
"using a non UTF-8 literal in `std::str::from_utf8`"
57+
}
58+
59+
declare_lint_pass!(InvalidFromUtf8 => [INVALID_FROM_UTF8_UNCHECKED, INVALID_FROM_UTF8]);
60+
61+
impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
62+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
63+
if let ExprKind::Call(path, [arg]) = expr.kind
64+
&& let ExprKind::Path(ref qpath) = path.kind
65+
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
66+
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
67+
&& [sym::str_from_utf8, sym::str_from_utf8_mut,
68+
sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item)
69+
{
70+
let lint = |utf8_error: Utf8Error| {
71+
let label = arg.span;
72+
let method = diag_item.as_str().strip_prefix("str_").unwrap();
73+
let method = format!("std::str::{method}");
74+
let valid_up_to = utf8_error.valid_up_to();
75+
let is_unchecked_variant = diag_item.as_str().contains("unchecked");
76+
77+
cx.emit_spanned_lint(
78+
if is_unchecked_variant { INVALID_FROM_UTF8_UNCHECKED } else { INVALID_FROM_UTF8 },
79+
expr.span,
80+
if is_unchecked_variant {
81+
InvalidFromUtf8Diag::Unchecked { method, valid_up_to, label }
82+
} else {
83+
InvalidFromUtf8Diag::Checked { method, valid_up_to, label }
84+
}
85+
)
86+
};
87+
88+
match &arg.kind {
89+
ExprKind::Lit(Spanned { node: lit, .. }) => {
90+
if let LitKind::ByteStr(bytes, _) = &lit
91+
&& let Err(utf8_error) = std::str::from_utf8(bytes)
92+
{
93+
lint(utf8_error);
94+
}
95+
},
96+
ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
97+
let elements = args.iter().map(|e|{
98+
match &e.kind {
99+
ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
100+
LitKind::Byte(b) => Some(*b),
101+
LitKind::Int(b, _) => Some(*b as u8),
102+
_ => None
103+
}
104+
_ => None
105+
}
106+
}).collect::<Option<Vec<_>>>();
107+
108+
if let Some(elements) = elements
109+
&& let Err(utf8_error) = std::str::from_utf8(&elements)
110+
{
111+
lint(utf8_error);
112+
}
113+
}
114+
_ => {}
115+
}
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)