Skip to content

Commit

Permalink
Auto merge of #112102 - Nilstrieb:rollup-ivu1hmc, r=Nilstrieb
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed May 30, 2023
2 parents 3266c36 + cc12182 commit a9251b6
Show file tree
Hide file tree
Showing 82 changed files with 796 additions and 434 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
));
Expand Down Expand Up @@ -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>(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/outlives/explicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
}
}

ty::EarlyBinder::new(required_predicates)
ty::EarlyBinder::bind(required_predicates)
})
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
46 changes: 14 additions & 32 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
self.suggest_call_as_method(
&mut diag,
segment,
arg_exprs,
call_expr,
expected
);
diag.emit();
}

let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
Expand Down Expand Up @@ -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
Expand All @@ -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(
Expand All @@ -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);
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
118 changes: 118 additions & 0 deletions compiler/rustc_lint/src/invalid_from_utf8.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
_ => {}
}
}
}
}
Loading

0 comments on commit a9251b6

Please sign in to comment.